[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:
551
domain/sftpFollowTerminalCwd.test.ts
Normal file
551
domain/sftpFollowTerminalCwd.test.ts
Normal file
@@ -0,0 +1,551 @@
|
||||
import test from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import {
|
||||
isFollowOriginStillCurrent,
|
||||
mergeLatestFollowTerminalCwdHostSetting,
|
||||
resolveHostFollowTerminalCwd,
|
||||
resolveSftpFollowTerminalCwdTargetHost,
|
||||
shouldApplyFollowTerminalCwdSyncResult,
|
||||
shouldClearBlockedFollowOnReach,
|
||||
shouldFollowTerminalCwdNavigate,
|
||||
shouldInvalidateFollowBookkeepingOnCwdChange,
|
||||
shouldLatchInitialFollowInterruption,
|
||||
shouldReleaseInitialFollowSyncAttempt,
|
||||
shouldResetInitialFollowTerminalCwdSync,
|
||||
} from "./sftpFollowTerminalCwd";
|
||||
|
||||
const base = {
|
||||
followEnabled: true,
|
||||
isVisible: true,
|
||||
terminalCwd: "/home/user/project",
|
||||
currentPath: "/home/user",
|
||||
connectionId: "conn-1",
|
||||
hasActiveWork: false,
|
||||
isConnected: true,
|
||||
};
|
||||
|
||||
test("shouldFollowTerminalCwdNavigate returns true when follow is on and paths differ", () => {
|
||||
assert.equal(shouldFollowTerminalCwdNavigate(base), true);
|
||||
});
|
||||
|
||||
test("shouldFollowTerminalCwdNavigate returns false when paths already match", () => {
|
||||
assert.equal(
|
||||
shouldFollowTerminalCwdNavigate({ ...base, currentPath: "/home/user/project" }),
|
||||
false,
|
||||
);
|
||||
});
|
||||
|
||||
test("shouldFollowTerminalCwdNavigate returns false when follow is disabled", () => {
|
||||
assert.equal(shouldFollowTerminalCwdNavigate({ ...base, followEnabled: false }), false);
|
||||
});
|
||||
|
||||
test("shouldFollowTerminalCwdNavigate returns false while interactive work is active", () => {
|
||||
assert.equal(shouldFollowTerminalCwdNavigate({ ...base, hasActiveWork: true }), false);
|
||||
});
|
||||
|
||||
test("shouldFollowTerminalCwdNavigate returns false without a known terminal cwd", () => {
|
||||
assert.equal(shouldFollowTerminalCwdNavigate({ ...base, terminalCwd: null }), false);
|
||||
});
|
||||
|
||||
test("shouldFollowTerminalCwdNavigate returns false when cwd is blocked after a failed follow", () => {
|
||||
assert.equal(
|
||||
shouldFollowTerminalCwdNavigate({
|
||||
...base,
|
||||
blockedFollow: { connectionId: "conn-1", terminalCwd: "/home/user/project" },
|
||||
}),
|
||||
false,
|
||||
);
|
||||
});
|
||||
|
||||
test("shouldFollowTerminalCwdNavigate ignores blocked cwd for a different connection", () => {
|
||||
assert.equal(
|
||||
shouldFollowTerminalCwdNavigate({
|
||||
...base,
|
||||
connectionId: "conn-2",
|
||||
blockedFollow: { connectionId: "conn-1", terminalCwd: "/home/user/project" },
|
||||
}),
|
||||
true,
|
||||
);
|
||||
});
|
||||
|
||||
test("shouldFollowTerminalCwdNavigate ignores blocked cwd when terminal cwd changed", () => {
|
||||
assert.equal(
|
||||
shouldFollowTerminalCwdNavigate({
|
||||
...base,
|
||||
terminalCwd: "/home/user/other",
|
||||
blockedFollow: { connectionId: "conn-1", terminalCwd: "/home/user/project" },
|
||||
}),
|
||||
true,
|
||||
);
|
||||
});
|
||||
|
||||
test("shouldFollowTerminalCwdNavigate does not recapture manual navigation after the cwd was handled", () => {
|
||||
assert.equal(
|
||||
shouldFollowTerminalCwdNavigate({
|
||||
...base,
|
||||
currentPath: "/srv/bookmark",
|
||||
handledFollow: { connectionId: "conn-1", terminalCwd: "/home/user/project" },
|
||||
}),
|
||||
false,
|
||||
);
|
||||
});
|
||||
|
||||
test("shouldFollowTerminalCwdNavigate resumes when the terminal cwd changes", () => {
|
||||
assert.equal(
|
||||
shouldFollowTerminalCwdNavigate({
|
||||
...base,
|
||||
terminalCwd: "/home/user/other",
|
||||
currentPath: "/srv/bookmark",
|
||||
handledFollow: { connectionId: "conn-1", terminalCwd: "/home/user/project" },
|
||||
}),
|
||||
true,
|
||||
);
|
||||
});
|
||||
|
||||
test("resolveHostFollowTerminalCwd inherits the global setting until the host overrides it", () => {
|
||||
assert.equal(resolveHostFollowTerminalCwd(undefined, true), true);
|
||||
assert.equal(resolveHostFollowTerminalCwd(undefined, false), false);
|
||||
assert.equal(resolveHostFollowTerminalCwd(true, false), true);
|
||||
assert.equal(resolveHostFollowTerminalCwd(false, true), false);
|
||||
});
|
||||
|
||||
test("resolveSftpFollowTerminalCwdTargetHost prefers the visible SFTP host", () => {
|
||||
const terminalHost = { id: "terminal-host" };
|
||||
const visibleHost = { id: "visible-sftp-host" };
|
||||
|
||||
assert.equal(
|
||||
resolveSftpFollowTerminalCwdTargetHost(visibleHost, terminalHost),
|
||||
visibleHost,
|
||||
);
|
||||
assert.equal(
|
||||
resolveSftpFollowTerminalCwdTargetHost(null, terminalHost),
|
||||
terminalHost,
|
||||
);
|
||||
});
|
||||
|
||||
test("visible SFTP host override can enable follow when terminal host inherits global off", () => {
|
||||
const terminalHost = { id: "terminal-host", sftpFollowTerminalCwd: undefined };
|
||||
const visibleHost = { id: "visible-sftp-host", sftpFollowTerminalCwd: true };
|
||||
const followHost = resolveSftpFollowTerminalCwdTargetHost(visibleHost, terminalHost);
|
||||
|
||||
assert.equal(resolveHostFollowTerminalCwd(followHost?.sftpFollowTerminalCwd, false), true);
|
||||
});
|
||||
|
||||
test("mergeLatestFollowTerminalCwdHostSetting refreshes the follow flag without losing display overrides", () => {
|
||||
const connectedHost = {
|
||||
id: "host-1",
|
||||
hostname: "session.example.com",
|
||||
sftpFollowTerminalCwd: false,
|
||||
};
|
||||
const latestHost = {
|
||||
id: "host-1",
|
||||
hostname: "vault.example.com",
|
||||
sftpFollowTerminalCwd: true,
|
||||
};
|
||||
|
||||
assert.deepEqual(
|
||||
mergeLatestFollowTerminalCwdHostSetting(connectedHost, latestHost),
|
||||
{
|
||||
id: "host-1",
|
||||
hostname: "session.example.com",
|
||||
sftpFollowTerminalCwd: true,
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
test("mergeLatestFollowTerminalCwdHostSetting keeps optimistic session override until vault updates", () => {
|
||||
const connectedHost = {
|
||||
id: "host-1",
|
||||
hostname: "session.example.com",
|
||||
sftpFollowTerminalCwd: false,
|
||||
};
|
||||
const latestHost = {
|
||||
id: "host-1",
|
||||
hostname: "vault.example.com",
|
||||
};
|
||||
|
||||
assert.deepEqual(
|
||||
mergeLatestFollowTerminalCwdHostSetting(connectedHost, latestHost, false),
|
||||
{
|
||||
id: "host-1",
|
||||
hostname: "session.example.com",
|
||||
sftpFollowTerminalCwd: false,
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
test("mergeLatestFollowTerminalCwdHostSetting drops stale session override when vault clears the follow flag", () => {
|
||||
const connectedHost = {
|
||||
id: "host-1",
|
||||
hostname: "session.example.com",
|
||||
sftpFollowTerminalCwd: true,
|
||||
};
|
||||
const latestHost = {
|
||||
id: "host-1",
|
||||
hostname: "vault.example.com",
|
||||
};
|
||||
|
||||
assert.deepEqual(
|
||||
mergeLatestFollowTerminalCwdHostSetting(connectedHost, latestHost),
|
||||
{
|
||||
id: "host-1",
|
||||
hostname: "session.example.com",
|
||||
sftpFollowTerminalCwd: undefined,
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
test("shouldClearBlockedFollowOnReach clears when the active connection reaches the blocked cwd", () => {
|
||||
assert.equal(
|
||||
shouldClearBlockedFollowOnReach(
|
||||
{ connectionId: "conn-1", terminalCwd: "/home/user/project" },
|
||||
"conn-1",
|
||||
"/home/user/project",
|
||||
false,
|
||||
),
|
||||
true,
|
||||
);
|
||||
});
|
||||
|
||||
test("shouldClearBlockedFollowOnReach keeps block while navigation is still loading", () => {
|
||||
assert.equal(
|
||||
shouldClearBlockedFollowOnReach(
|
||||
{ connectionId: "conn-1", terminalCwd: "/home/user/project" },
|
||||
"conn-1",
|
||||
"/home/user/project",
|
||||
true,
|
||||
),
|
||||
false,
|
||||
);
|
||||
});
|
||||
|
||||
test("shouldApplyFollowTerminalCwdSyncResult rejects stale follow results after cwd changes", () => {
|
||||
let generation = 0;
|
||||
const followA = generation;
|
||||
|
||||
generation += 1;
|
||||
const followB = generation;
|
||||
|
||||
assert.equal(
|
||||
shouldApplyFollowTerminalCwdSyncResult({
|
||||
syncGeneration: followB,
|
||||
currentGeneration: generation,
|
||||
followEnabled: true,
|
||||
canFollow: true,
|
||||
}),
|
||||
true,
|
||||
);
|
||||
assert.equal(
|
||||
shouldApplyFollowTerminalCwdSyncResult({
|
||||
syncGeneration: followA,
|
||||
currentGeneration: generation,
|
||||
followEnabled: true,
|
||||
canFollow: true,
|
||||
}),
|
||||
false,
|
||||
);
|
||||
});
|
||||
|
||||
test("shouldApplyFollowTerminalCwdSyncResult rejects results after follow is unavailable", () => {
|
||||
assert.equal(
|
||||
shouldApplyFollowTerminalCwdSyncResult({
|
||||
syncGeneration: 2,
|
||||
currentGeneration: 2,
|
||||
followEnabled: false,
|
||||
canFollow: true,
|
||||
}),
|
||||
false,
|
||||
);
|
||||
assert.equal(
|
||||
shouldApplyFollowTerminalCwdSyncResult({
|
||||
syncGeneration: 2,
|
||||
currentGeneration: 2,
|
||||
followEnabled: true,
|
||||
canFollow: false,
|
||||
}),
|
||||
false,
|
||||
);
|
||||
});
|
||||
|
||||
test("isFollowOriginStillCurrent treats a missing origin as bound to the live focused terminal", () => {
|
||||
assert.equal(isFollowOriginStillCurrent({
|
||||
expectedOriginId: null,
|
||||
liveOriginId: null,
|
||||
}), true);
|
||||
assert.equal(isFollowOriginStillCurrent({
|
||||
expectedOriginId: null,
|
||||
liveOriginId: "mosh-b",
|
||||
}), false);
|
||||
assert.equal(isFollowOriginStillCurrent({
|
||||
expectedOriginId: "mosh-a",
|
||||
liveOriginId: "mosh-b",
|
||||
}), false);
|
||||
assert.equal(isFollowOriginStillCurrent({
|
||||
expectedOriginId: "mosh-a",
|
||||
liveOriginId: "mosh-a",
|
||||
}), true);
|
||||
});
|
||||
|
||||
test("shouldApplyFollowTerminalCwdSyncResult rejects a null origin after focus appears", () => {
|
||||
assert.equal(
|
||||
shouldApplyFollowTerminalCwdSyncResult({
|
||||
syncGeneration: 2,
|
||||
currentGeneration: 2,
|
||||
followEnabled: true,
|
||||
canFollow: true,
|
||||
expectedSessionId: null,
|
||||
liveSessionId: null,
|
||||
}),
|
||||
true,
|
||||
);
|
||||
assert.equal(
|
||||
shouldApplyFollowTerminalCwdSyncResult({
|
||||
syncGeneration: 2,
|
||||
currentGeneration: 2,
|
||||
followEnabled: true,
|
||||
canFollow: true,
|
||||
expectedSessionId: null,
|
||||
liveSessionId: "mosh-b",
|
||||
}),
|
||||
false,
|
||||
);
|
||||
});
|
||||
|
||||
test("shouldApplyFollowTerminalCwdSyncResult rejects results after the focused session changes", () => {
|
||||
assert.equal(
|
||||
shouldApplyFollowTerminalCwdSyncResult({
|
||||
syncGeneration: 2,
|
||||
currentGeneration: 2,
|
||||
followEnabled: true,
|
||||
canFollow: true,
|
||||
expectedSessionId: "session-a",
|
||||
liveSessionId: "session-b",
|
||||
}),
|
||||
false,
|
||||
);
|
||||
assert.equal(
|
||||
shouldApplyFollowTerminalCwdSyncResult({
|
||||
syncGeneration: 2,
|
||||
currentGeneration: 2,
|
||||
followEnabled: true,
|
||||
canFollow: true,
|
||||
expectedSessionId: "session-a",
|
||||
liveSessionId: "session-a",
|
||||
}),
|
||||
true,
|
||||
);
|
||||
});
|
||||
|
||||
test("shouldApplyFollowTerminalCwdSyncResult rejects results for an old connection", () => {
|
||||
assert.equal(
|
||||
shouldApplyFollowTerminalCwdSyncResult({
|
||||
syncGeneration: 2,
|
||||
currentGeneration: 2,
|
||||
followEnabled: true,
|
||||
canFollow: true,
|
||||
expectedConnectionId: "conn-1",
|
||||
liveConnectionId: "conn-2",
|
||||
paneConnectionId: "conn-2",
|
||||
}),
|
||||
false,
|
||||
);
|
||||
});
|
||||
|
||||
test("shouldApplyFollowTerminalCwdSyncResult rejects results for an old terminal cwd", () => {
|
||||
assert.equal(
|
||||
shouldApplyFollowTerminalCwdSyncResult({
|
||||
syncGeneration: 2,
|
||||
currentGeneration: 2,
|
||||
followEnabled: true,
|
||||
canFollow: true,
|
||||
expectedConnectionId: "conn-1",
|
||||
liveConnectionId: "conn-1",
|
||||
paneConnectionId: "conn-1",
|
||||
expectedTerminalCwd: "/srv/old",
|
||||
liveTerminalCwd: "/srv/new",
|
||||
}),
|
||||
false,
|
||||
);
|
||||
});
|
||||
|
||||
test("shouldApplyFollowTerminalCwdSyncResult rejects missing live cwd when required", () => {
|
||||
assert.equal(
|
||||
shouldApplyFollowTerminalCwdSyncResult({
|
||||
syncGeneration: 2,
|
||||
currentGeneration: 2,
|
||||
followEnabled: true,
|
||||
canFollow: true,
|
||||
expectedConnectionId: "conn-1",
|
||||
liveConnectionId: "conn-1",
|
||||
paneConnectionId: "conn-1",
|
||||
expectedTerminalCwd: "/srv/project",
|
||||
liveTerminalCwd: null,
|
||||
requireLiveTerminalCwd: true,
|
||||
}),
|
||||
false,
|
||||
);
|
||||
});
|
||||
|
||||
test("shouldApplyFollowTerminalCwdSyncResult allows missing live cwd when target was fetched fresh", () => {
|
||||
assert.equal(
|
||||
shouldApplyFollowTerminalCwdSyncResult({
|
||||
syncGeneration: 2,
|
||||
currentGeneration: 2,
|
||||
followEnabled: true,
|
||||
canFollow: true,
|
||||
expectedConnectionId: "conn-1",
|
||||
liveConnectionId: "conn-1",
|
||||
paneConnectionId: "conn-1",
|
||||
expectedTerminalCwd: "/srv/project",
|
||||
liveTerminalCwd: null,
|
||||
}),
|
||||
true,
|
||||
);
|
||||
});
|
||||
|
||||
test("follow bookkeeping keeps handled state across hidden-panel null cwd transitions", () => {
|
||||
// Hidden panels receive activeTerminalCwd={null} and get the last live value
|
||||
// back on reshow: the visibility transitions may not drop handled follow
|
||||
// bookkeeping when the cwd did not actually change.
|
||||
assert.equal(
|
||||
shouldInvalidateFollowBookkeepingOnCwdChange({
|
||||
nextCwd: null,
|
||||
lastCwd: "/home/user/project",
|
||||
isVisible: false,
|
||||
}),
|
||||
false,
|
||||
);
|
||||
assert.equal(
|
||||
shouldInvalidateFollowBookkeepingOnCwdChange({
|
||||
nextCwd: "/home/user/project",
|
||||
lastCwd: "/home/user/project",
|
||||
isVisible: false,
|
||||
}),
|
||||
false,
|
||||
);
|
||||
assert.equal(
|
||||
shouldInvalidateFollowBookkeepingOnCwdChange({
|
||||
nextCwd: "/home/user/project",
|
||||
lastCwd: "/home/user/project",
|
||||
isVisible: true,
|
||||
}),
|
||||
false,
|
||||
);
|
||||
assert.equal(
|
||||
shouldInvalidateFollowBookkeepingOnCwdChange({
|
||||
nextCwd: null,
|
||||
lastCwd: null,
|
||||
isVisible: false,
|
||||
}),
|
||||
false,
|
||||
);
|
||||
});
|
||||
|
||||
test("follow bookkeeping invalidates on a real terminal cwd change", () => {
|
||||
assert.equal(
|
||||
shouldInvalidateFollowBookkeepingOnCwdChange({
|
||||
nextCwd: "/home/user/other",
|
||||
lastCwd: "/home/user/project",
|
||||
isVisible: true,
|
||||
}),
|
||||
true,
|
||||
);
|
||||
// A cwd that changed while the panel was hidden still invalidates on reshow.
|
||||
assert.equal(
|
||||
shouldInvalidateFollowBookkeepingOnCwdChange({
|
||||
nextCwd: "/home/user/other",
|
||||
lastCwd: null,
|
||||
isVisible: true,
|
||||
}),
|
||||
true,
|
||||
);
|
||||
// A `null` while the surface is visible means the linked terminal session
|
||||
// changed (or closed) and its cwd cache is empty: in-flight follow results
|
||||
// of the previous session must be invalidated.
|
||||
assert.equal(
|
||||
shouldInvalidateFollowBookkeepingOnCwdChange({
|
||||
nextCwd: null,
|
||||
lastCwd: "/home/user/project",
|
||||
isVisible: true,
|
||||
}),
|
||||
true,
|
||||
);
|
||||
});
|
||||
|
||||
test("first-open sync reset re-arms on a replaced connection", () => {
|
||||
assert.equal(
|
||||
shouldResetInitialFollowTerminalCwdSync({
|
||||
isVisible: true,
|
||||
ownerPanelOpen: true,
|
||||
connectionId: "conn-2",
|
||||
trackedConnectionId: "conn-1",
|
||||
}),
|
||||
true,
|
||||
);
|
||||
});
|
||||
|
||||
test("first-open sync reset re-arms after a fresh open on the same connection", () => {
|
||||
assert.equal(
|
||||
shouldResetInitialFollowTerminalCwdSync({
|
||||
isVisible: false,
|
||||
ownerPanelOpen: false,
|
||||
connectionId: "conn-1",
|
||||
trackedConnectionId: "conn-1",
|
||||
}),
|
||||
true,
|
||||
);
|
||||
});
|
||||
|
||||
test("first-open sync reset survives hiding the surface while the owner panel stays open", () => {
|
||||
// Terminal tab switches / side-panel tool switches keep the panel mounted
|
||||
// and open: the user's browsed directory and filename filter must survive.
|
||||
assert.equal(
|
||||
shouldResetInitialFollowTerminalCwdSync({
|
||||
isVisible: false,
|
||||
ownerPanelOpen: true,
|
||||
connectionId: "conn-1",
|
||||
trackedConnectionId: "conn-1",
|
||||
}),
|
||||
false,
|
||||
);
|
||||
assert.equal(
|
||||
shouldResetInitialFollowTerminalCwdSync({
|
||||
isVisible: true,
|
||||
ownerPanelOpen: true,
|
||||
connectionId: "conn-1",
|
||||
trackedConnectionId: "conn-1",
|
||||
}),
|
||||
false,
|
||||
);
|
||||
});
|
||||
|
||||
test("first-open sync attempt is released while visible or after the owner panel closed", () => {
|
||||
assert.equal(shouldReleaseInitialFollowSyncAttempt({ isVisible: true, ownerPanelOpen: true }), true);
|
||||
assert.equal(shouldReleaseInitialFollowSyncAttempt({ isVisible: true, ownerPanelOpen: false }), true);
|
||||
assert.equal(shouldReleaseInitialFollowSyncAttempt({ isVisible: false, ownerPanelOpen: false }), true);
|
||||
});
|
||||
|
||||
test("first-open sync attempt stays consumed while hidden with the owner panel open", () => {
|
||||
// Terminal tab switch while the fresh-CWD probe is still pending: the
|
||||
// interrupted attempt must not re-arm, or returning to the tab re-runs the
|
||||
// first-open sync and navigates away from the browsed directory.
|
||||
assert.equal(shouldReleaseInitialFollowSyncAttempt({ isVisible: false, ownerPanelOpen: true }), false);
|
||||
});
|
||||
|
||||
test("first-open probe is latched as interrupted on a hide with the owner panel open", () => {
|
||||
// Terminal-tab switch while the fresh-CWD probe is pending: the probe must be
|
||||
// latched as interrupted so it cannot navigate once the tab is reshown.
|
||||
assert.equal(
|
||||
shouldLatchInitialFollowInterruption({ isVisible: false, ownerPanelOpen: true }),
|
||||
true,
|
||||
);
|
||||
assert.equal(
|
||||
shouldLatchInitialFollowInterruption({ isVisible: true, ownerPanelOpen: true }),
|
||||
false,
|
||||
);
|
||||
// A panel close is not an interruption latch: the reset guard re-arms there.
|
||||
assert.equal(
|
||||
shouldLatchInitialFollowInterruption({ isVisible: false, ownerPanelOpen: false }),
|
||||
false,
|
||||
);
|
||||
});
|
||||
Reference in New Issue
Block a user