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
658 lines
19 KiB
TypeScript
658 lines
19 KiB
TypeScript
import test from "node:test";
|
|
import assert from "node:assert/strict";
|
|
|
|
import type { Host } from "../domain/models";
|
|
import {
|
|
AUTO_RUN_SNIPPET_LINE_DELAY_MS,
|
|
resolveDisconnectedDialogTerminalRoot,
|
|
restoreTerminalFocusFromDisconnectedDialog,
|
|
shouldClaimDisconnectedDialogFocus,
|
|
shouldHideConnectingDialogForConnectionReuse,
|
|
shouldDelayAutoRunSnippetInput,
|
|
shouldReconnectDisconnectedDialogOnEnterKey,
|
|
shouldRestoreDisconnectedDialogTerminalFocus,
|
|
shouldShowTerminalDisconnectedNotice,
|
|
shouldShowTerminalConnectionDialog,
|
|
} from "./terminal/terminalHelpers";
|
|
|
|
const host = (overrides: Partial<Host> = {}): Host => ({
|
|
id: "host-1",
|
|
label: "Host",
|
|
hostname: "example.com",
|
|
username: "alice",
|
|
authMethod: "password",
|
|
...overrides,
|
|
});
|
|
|
|
test("disconnected dialog reconnects on plain Enter when no control owns focus", () => {
|
|
assert.equal(
|
|
shouldReconnectDisconnectedDialogOnEnterKey({
|
|
key: "Enter",
|
|
enabled: true,
|
|
}),
|
|
true,
|
|
);
|
|
assert.equal(
|
|
shouldReconnectDisconnectedDialogOnEnterKey({
|
|
key: "Enter",
|
|
enabled: false,
|
|
}),
|
|
false,
|
|
);
|
|
assert.equal(
|
|
shouldReconnectDisconnectedDialogOnEnterKey({
|
|
key: "a",
|
|
enabled: true,
|
|
}),
|
|
false,
|
|
);
|
|
assert.equal(
|
|
shouldReconnectDisconnectedDialogOnEnterKey({
|
|
key: "Enter",
|
|
enabled: true,
|
|
shiftKey: true,
|
|
}),
|
|
false,
|
|
);
|
|
});
|
|
|
|
test("disconnected dialog leaves Enter to focused buttons and inputs", () => {
|
|
class FakeElement {
|
|
constructor(private readonly selectorMatch: boolean) {}
|
|
closest(selector: string) {
|
|
void selector;
|
|
return this.selectorMatch ? this : null;
|
|
}
|
|
}
|
|
const previousHTMLElement = globalThis.HTMLElement;
|
|
// @ts-expect-error test double for DOM instanceof checks
|
|
globalThis.HTMLElement = FakeElement;
|
|
try {
|
|
const buttonLike = new FakeElement(true);
|
|
const plain = new FakeElement(false);
|
|
assert.equal(
|
|
shouldReconnectDisconnectedDialogOnEnterKey({
|
|
key: "Enter",
|
|
enabled: true,
|
|
target: buttonLike as unknown as EventTarget,
|
|
}),
|
|
false,
|
|
);
|
|
assert.equal(
|
|
shouldReconnectDisconnectedDialogOnEnterKey({
|
|
key: "Enter",
|
|
enabled: true,
|
|
target: plain as unknown as EventTarget,
|
|
}),
|
|
true,
|
|
);
|
|
} finally {
|
|
globalThis.HTMLElement = previousHTMLElement;
|
|
}
|
|
});
|
|
|
|
test("disconnected dialog focus claim never steals from other panes", () => {
|
|
class FakeNode {
|
|
constructor(
|
|
private readonly opts: {
|
|
id: string;
|
|
parent?: FakeNode | null;
|
|
interactive?: boolean;
|
|
children?: FakeNode[];
|
|
},
|
|
) {
|
|
for (const child of opts.children ?? []) {
|
|
child.opts.parent = this;
|
|
}
|
|
}
|
|
get parentElement() {
|
|
return this.opts.parent ?? null;
|
|
}
|
|
contains(other: FakeNode | null) {
|
|
if (!other) return false;
|
|
let cur: FakeNode | null | undefined = other;
|
|
while (cur) {
|
|
if (cur === this) return true;
|
|
cur = cur.opts.parent;
|
|
}
|
|
return false;
|
|
}
|
|
closest(selector: string) {
|
|
if (selector.includes("button") && this.opts.interactive) return this;
|
|
return null;
|
|
}
|
|
querySelector(selector: string) {
|
|
if (!selector.includes("xterm-helper-textarea")) return null;
|
|
return (this.opts.children ?? []).find((c) => c.opts.id === "textarea") ?? null;
|
|
}
|
|
focusCalls = 0;
|
|
focus() {
|
|
this.focusCalls += 1;
|
|
}
|
|
}
|
|
|
|
const previousHTMLElement = globalThis.HTMLElement;
|
|
// @ts-expect-error test double for DOM instanceof checks
|
|
globalThis.HTMLElement = FakeNode;
|
|
try {
|
|
const body = new FakeNode({ id: "body" });
|
|
const otherPane = new FakeNode({ id: "other" });
|
|
const textarea = new FakeNode({ id: "textarea" });
|
|
const dialogButton = new FakeNode({ id: "btn", interactive: true });
|
|
const dialog = new FakeNode({ id: "dialog", children: [dialogButton] });
|
|
const session = new FakeNode({ id: "session", children: [textarea, dialog] });
|
|
|
|
assert.equal(
|
|
shouldClaimDisconnectedDialogFocus({
|
|
activeElement: null,
|
|
dialogNode: dialog as unknown as HTMLElement,
|
|
sessionRoot: session as unknown as Element,
|
|
documentBody: body as unknown as Element,
|
|
}),
|
|
true,
|
|
);
|
|
assert.equal(
|
|
shouldClaimDisconnectedDialogFocus({
|
|
activeElement: body as unknown as Element,
|
|
dialogNode: dialog as unknown as HTMLElement,
|
|
sessionRoot: session as unknown as Element,
|
|
documentBody: body as unknown as Element,
|
|
}),
|
|
true,
|
|
);
|
|
// Unfocused split sibling must not claim when focus is on body/null.
|
|
assert.equal(
|
|
shouldClaimDisconnectedDialogFocus({
|
|
activeElement: null,
|
|
dialogNode: dialog as unknown as HTMLElement,
|
|
sessionRoot: session as unknown as Element,
|
|
documentBody: body as unknown as Element,
|
|
isFocusedPane: false,
|
|
}),
|
|
false,
|
|
);
|
|
assert.equal(
|
|
shouldClaimDisconnectedDialogFocus({
|
|
activeElement: body as unknown as Element,
|
|
dialogNode: dialog as unknown as HTMLElement,
|
|
sessionRoot: session as unknown as Element,
|
|
documentBody: body as unknown as Element,
|
|
isFocusedPane: false,
|
|
}),
|
|
false,
|
|
);
|
|
assert.equal(
|
|
shouldClaimDisconnectedDialogFocus({
|
|
activeElement: body as unknown as Element,
|
|
dialogNode: dialog as unknown as HTMLElement,
|
|
sessionRoot: session as unknown as Element,
|
|
documentBody: body as unknown as Element,
|
|
isFocusedPane: true,
|
|
}),
|
|
true,
|
|
);
|
|
assert.equal(
|
|
shouldClaimDisconnectedDialogFocus({
|
|
activeElement: textarea as unknown as Element,
|
|
dialogNode: dialog as unknown as HTMLElement,
|
|
sessionRoot: session as unknown as Element,
|
|
documentBody: body as unknown as Element,
|
|
}),
|
|
true,
|
|
);
|
|
assert.equal(
|
|
shouldClaimDisconnectedDialogFocus({
|
|
activeElement: otherPane as unknown as Element,
|
|
dialogNode: dialog as unknown as HTMLElement,
|
|
sessionRoot: session as unknown as Element,
|
|
documentBody: body as unknown as Element,
|
|
}),
|
|
false,
|
|
);
|
|
assert.equal(
|
|
shouldClaimDisconnectedDialogFocus({
|
|
activeElement: dialogButton as unknown as Element,
|
|
dialogNode: dialog as unknown as HTMLElement,
|
|
sessionRoot: session as unknown as Element,
|
|
documentBody: body as unknown as Element,
|
|
}),
|
|
false,
|
|
);
|
|
assert.equal(
|
|
shouldClaimDisconnectedDialogFocus({
|
|
activeElement: dialog as unknown as Element,
|
|
dialogNode: dialog as unknown as HTMLElement,
|
|
sessionRoot: session as unknown as Element,
|
|
documentBody: body as unknown as Element,
|
|
}),
|
|
false,
|
|
);
|
|
|
|
assert.equal(
|
|
restoreTerminalFocusFromDisconnectedDialog({
|
|
activeElement: dialog as unknown as Element,
|
|
dialogNode: dialog as unknown as HTMLElement,
|
|
sessionRoot: session as unknown as Element,
|
|
documentBody: body as unknown as Element,
|
|
}),
|
|
true,
|
|
);
|
|
assert.equal(textarea.focusCalls, 1);
|
|
// After React removes the focused dialog, the browser parks focus on body
|
|
// before passive-effect cleanup runs — still restore to this session's xterm.
|
|
assert.equal(
|
|
restoreTerminalFocusFromDisconnectedDialog({
|
|
activeElement: body as unknown as Element,
|
|
dialogNode: dialog as unknown as HTMLElement,
|
|
sessionRoot: session as unknown as Element,
|
|
documentBody: body as unknown as Element,
|
|
}),
|
|
true,
|
|
);
|
|
assert.equal(textarea.focusCalls, 2);
|
|
assert.equal(
|
|
restoreTerminalFocusFromDisconnectedDialog({
|
|
activeElement: otherPane as unknown as Element,
|
|
dialogNode: dialog as unknown as HTMLElement,
|
|
sessionRoot: session as unknown as Element,
|
|
documentBody: body as unknown as Element,
|
|
}),
|
|
false,
|
|
);
|
|
assert.equal(textarea.focusCalls, 2);
|
|
|
|
// Popup terminals have no data-session-id ancestor — restore via local tree walk.
|
|
const popupTextarea = new FakeNode({ id: "textarea" });
|
|
const popupDialog = new FakeNode({ id: "dialog" });
|
|
const popupRoot = new FakeNode({ id: "popup-root", children: [popupTextarea, popupDialog] });
|
|
assert.equal(
|
|
resolveDisconnectedDialogTerminalRoot(popupDialog as unknown as Element, null),
|
|
popupRoot as unknown as Element,
|
|
);
|
|
assert.equal(
|
|
restoreTerminalFocusFromDisconnectedDialog({
|
|
activeElement: popupDialog as unknown as Element,
|
|
dialogNode: popupDialog as unknown as HTMLElement,
|
|
sessionRoot: null,
|
|
documentBody: body as unknown as Element,
|
|
}),
|
|
true,
|
|
);
|
|
assert.equal(popupTextarea.focusCalls, 1);
|
|
assert.equal(
|
|
shouldClaimDisconnectedDialogFocus({
|
|
activeElement: popupTextarea as unknown as Element,
|
|
dialogNode: popupDialog as unknown as HTMLElement,
|
|
sessionRoot: null,
|
|
documentBody: body as unknown as Element,
|
|
}),
|
|
true,
|
|
);
|
|
// Detached popup dialog (parent cleared) + body focus: use captured terminal root.
|
|
popupDialog.opts.parent = null;
|
|
assert.equal(
|
|
restoreTerminalFocusFromDisconnectedDialog({
|
|
activeElement: body as unknown as Element,
|
|
dialogNode: popupDialog as unknown as HTMLElement,
|
|
sessionRoot: popupRoot as unknown as Element,
|
|
documentBody: body as unknown as Element,
|
|
}),
|
|
true,
|
|
);
|
|
assert.equal(popupTextarea.focusCalls, 2);
|
|
|
|
// Unfocused split sibling must not restore when browser parked focus on body.
|
|
assert.equal(
|
|
restoreTerminalFocusFromDisconnectedDialog({
|
|
activeElement: body as unknown as Element,
|
|
dialogNode: dialog as unknown as HTMLElement,
|
|
sessionRoot: session as unknown as Element,
|
|
documentBody: body as unknown as Element,
|
|
isFocusedPane: false,
|
|
}),
|
|
false,
|
|
);
|
|
assert.equal(textarea.focusCalls, 2);
|
|
assert.equal(
|
|
restoreTerminalFocusFromDisconnectedDialog({
|
|
activeElement: body as unknown as Element,
|
|
dialogNode: dialog as unknown as HTMLElement,
|
|
sessionRoot: session as unknown as Element,
|
|
documentBody: body as unknown as Element,
|
|
isFocusedPane: true,
|
|
}),
|
|
true,
|
|
);
|
|
assert.equal(textarea.focusCalls, 3);
|
|
// Dialog actually owned focus — restore even if pane focus flag flipped.
|
|
assert.equal(
|
|
restoreTerminalFocusFromDisconnectedDialog({
|
|
activeElement: dialog as unknown as Element,
|
|
dialogNode: dialog as unknown as HTMLElement,
|
|
sessionRoot: session as unknown as Element,
|
|
documentBody: body as unknown as Element,
|
|
isFocusedPane: false,
|
|
}),
|
|
true,
|
|
);
|
|
assert.equal(textarea.focusCalls, 4);
|
|
} finally {
|
|
globalThis.HTMLElement = previousHTMLElement;
|
|
}
|
|
});
|
|
|
|
test("xterm focus restore is skipped while the connection overlay stays mounted", () => {
|
|
assert.equal(
|
|
shouldRestoreDisconnectedDialogTerminalFocus({ isConnected: true } as HTMLElement),
|
|
false,
|
|
);
|
|
assert.equal(
|
|
shouldRestoreDisconnectedDialogTerminalFocus({ isConnected: false } as HTMLElement),
|
|
true,
|
|
);
|
|
assert.equal(shouldRestoreDisconnectedDialogTerminalFocus(null), false);
|
|
});
|
|
|
|
test("connection dialog is hidden while a reused SSH channel is opening", () => {
|
|
assert.equal(
|
|
shouldShowTerminalConnectionDialog({
|
|
status: "connecting",
|
|
isLocalConnection: false,
|
|
isSerialConnection: false,
|
|
isDisconnectedDialogDismissed: false,
|
|
hideConnectingDialogForConnectionReuse: true,
|
|
}),
|
|
false,
|
|
);
|
|
});
|
|
|
|
test("connection dialog remains visible when reuse is not actually supported", () => {
|
|
assert.equal(
|
|
shouldShowTerminalConnectionDialog({
|
|
status: "connecting",
|
|
isLocalConnection: false,
|
|
isSerialConnection: false,
|
|
isDisconnectedDialogDismissed: false,
|
|
hideConnectingDialogForConnectionReuse: false,
|
|
}),
|
|
true,
|
|
);
|
|
});
|
|
|
|
test("connection dialog still appears for fresh remote connections", () => {
|
|
assert.equal(
|
|
shouldShowTerminalConnectionDialog({
|
|
status: "connecting",
|
|
isLocalConnection: false,
|
|
isSerialConnection: false,
|
|
isDisconnectedDialogDismissed: false,
|
|
}),
|
|
true,
|
|
);
|
|
});
|
|
|
|
test("connection dialog keeps existing local and disconnected behavior", () => {
|
|
assert.equal(
|
|
shouldShowTerminalConnectionDialog({
|
|
status: "connecting",
|
|
isLocalConnection: true,
|
|
isSerialConnection: false,
|
|
isDisconnectedDialogDismissed: false,
|
|
}),
|
|
false,
|
|
);
|
|
assert.equal(
|
|
shouldShowTerminalConnectionDialog({
|
|
status: "connected",
|
|
isLocalConnection: false,
|
|
isSerialConnection: false,
|
|
isDisconnectedDialogDismissed: false,
|
|
}),
|
|
false,
|
|
);
|
|
assert.equal(
|
|
shouldShowTerminalConnectionDialog({
|
|
status: "disconnected",
|
|
isLocalConnection: false,
|
|
isSerialConnection: false,
|
|
isDisconnectedDialogDismissed: true,
|
|
}),
|
|
false,
|
|
);
|
|
});
|
|
|
|
test("established sessions use the selected disconnected presentation", () => {
|
|
const base = {
|
|
status: "disconnected" as const,
|
|
hasEverConnected: true,
|
|
};
|
|
|
|
assert.equal(
|
|
shouldShowTerminalDisconnectedNotice({
|
|
...base,
|
|
disconnectedNoticeMode: "terminal",
|
|
}),
|
|
true,
|
|
);
|
|
assert.equal(
|
|
shouldShowTerminalConnectionDialog({
|
|
...base,
|
|
disconnectedNoticeMode: "terminal",
|
|
isLocalConnection: false,
|
|
isSerialConnection: false,
|
|
isDisconnectedDialogDismissed: false,
|
|
}),
|
|
false,
|
|
);
|
|
assert.equal(
|
|
shouldShowTerminalDisconnectedNotice({
|
|
...base,
|
|
disconnectedNoticeMode: "dialog",
|
|
}),
|
|
false,
|
|
);
|
|
assert.equal(
|
|
shouldShowTerminalConnectionDialog({
|
|
...base,
|
|
disconnectedNoticeMode: "dialog",
|
|
isLocalConnection: false,
|
|
isSerialConnection: false,
|
|
isDisconnectedDialogDismissed: false,
|
|
}),
|
|
true,
|
|
);
|
|
});
|
|
|
|
test("terminal notice never hides first-connect failures or restored session guidance", () => {
|
|
const dialogArgs = {
|
|
status: "disconnected" as const,
|
|
disconnectedNoticeMode: "terminal" as const,
|
|
isLocalConnection: false,
|
|
isSerialConnection: false,
|
|
isDisconnectedDialogDismissed: false,
|
|
};
|
|
|
|
assert.equal(
|
|
shouldShowTerminalDisconnectedNotice({
|
|
status: "disconnected",
|
|
disconnectedNoticeMode: "terminal",
|
|
hasEverConnected: false,
|
|
}),
|
|
false,
|
|
);
|
|
assert.equal(
|
|
shouldShowTerminalConnectionDialog({ ...dialogArgs, hasEverConnected: false }),
|
|
true,
|
|
);
|
|
assert.equal(
|
|
shouldShowTerminalDisconnectedNotice({
|
|
status: "disconnected",
|
|
disconnectedNoticeMode: "terminal",
|
|
hasEverConnected: true,
|
|
restoreState: "restored-disconnected",
|
|
}),
|
|
false,
|
|
);
|
|
assert.equal(
|
|
shouldShowTerminalConnectionDialog({
|
|
...dialogArgs,
|
|
hasEverConnected: true,
|
|
restoreState: "restored-disconnected",
|
|
}),
|
|
true,
|
|
);
|
|
});
|
|
|
|
test("terminal notice is absent while connected", () => {
|
|
assert.equal(
|
|
shouldShowTerminalDisconnectedNotice({
|
|
status: "connected",
|
|
disconnectedNoticeMode: "terminal",
|
|
hasEverConnected: true,
|
|
}),
|
|
false,
|
|
);
|
|
});
|
|
|
|
test("established manual reconnect stays non-blocking until input is required", () => {
|
|
const base = {
|
|
status: "connecting" as const,
|
|
disconnectedNoticeMode: "terminal" as const,
|
|
hasEverConnected: true,
|
|
isReconnectActive: true,
|
|
};
|
|
|
|
assert.equal(shouldShowTerminalDisconnectedNotice(base), true);
|
|
assert.equal(
|
|
shouldShowTerminalConnectionDialog({
|
|
...base,
|
|
isLocalConnection: false,
|
|
isSerialConnection: false,
|
|
isDisconnectedDialogDismissed: false,
|
|
}),
|
|
false,
|
|
);
|
|
|
|
assert.equal(
|
|
shouldShowTerminalDisconnectedNotice({ ...base, requiresUserInput: true }),
|
|
false,
|
|
);
|
|
assert.equal(
|
|
shouldShowTerminalConnectionDialog({
|
|
...base,
|
|
requiresUserInput: true,
|
|
isLocalConnection: false,
|
|
isSerialConnection: false,
|
|
isDisconnectedDialogDismissed: false,
|
|
}),
|
|
true,
|
|
);
|
|
});
|
|
|
|
test("established automatic reconnect stays non-blocking until input is required", () => {
|
|
const base = {
|
|
status: "connecting" as const,
|
|
disconnectedNoticeMode: "terminal" as const,
|
|
hasEverConnected: true,
|
|
isReconnectActive: true,
|
|
};
|
|
|
|
assert.equal(shouldShowTerminalDisconnectedNotice(base), true);
|
|
assert.equal(
|
|
shouldShowTerminalConnectionDialog({
|
|
...base,
|
|
isLocalConnection: false,
|
|
isSerialConnection: false,
|
|
isDisconnectedDialogDismissed: false,
|
|
}),
|
|
false,
|
|
);
|
|
|
|
assert.equal(
|
|
shouldShowTerminalDisconnectedNotice({ ...base, requiresUserInput: true }),
|
|
false,
|
|
);
|
|
assert.equal(
|
|
shouldShowTerminalConnectionDialog({
|
|
...base,
|
|
requiresUserInput: true,
|
|
isLocalConnection: false,
|
|
isSerialConnection: false,
|
|
isDisconnectedDialogDismissed: false,
|
|
}),
|
|
true,
|
|
);
|
|
});
|
|
|
|
test("connection reuse hides connecting dialog only while reuse is still possible", () => {
|
|
assert.equal(
|
|
shouldHideConnectingDialogForConnectionReuse({
|
|
reuseConnectionFromSessionId: undefined,
|
|
host: host(),
|
|
connectionReuseFellBack: false,
|
|
}),
|
|
false,
|
|
);
|
|
assert.equal(
|
|
shouldHideConnectingDialogForConnectionReuse({
|
|
reuseConnectionFromSessionId: "source-session",
|
|
host: host(),
|
|
connectionReuseFellBack: false,
|
|
}),
|
|
true,
|
|
);
|
|
assert.equal(
|
|
shouldHideConnectingDialogForConnectionReuse({
|
|
reuseConnectionFromSessionId: "source-session",
|
|
host: host({ x11Forwarding: true }),
|
|
connectionReuseFellBack: false,
|
|
}),
|
|
false,
|
|
);
|
|
assert.equal(
|
|
shouldHideConnectingDialogForConnectionReuse({
|
|
reuseConnectionFromSessionId: "source-session",
|
|
host: host({ moshEnabled: true }),
|
|
connectionReuseFellBack: false,
|
|
}),
|
|
false,
|
|
);
|
|
assert.equal(
|
|
shouldHideConnectingDialogForConnectionReuse({
|
|
reuseConnectionFromSessionId: "source-session",
|
|
host: host({ etEnabled: true }),
|
|
connectionReuseFellBack: false,
|
|
}),
|
|
false,
|
|
);
|
|
assert.equal(
|
|
shouldHideConnectingDialogForConnectionReuse({
|
|
reuseConnectionFromSessionId: "source-session",
|
|
host: host(),
|
|
connectionReuseFellBack: true,
|
|
}),
|
|
false,
|
|
);
|
|
});
|
|
|
|
test("auto-run snippets only delay multi-line input in line-by-line mode", () => {
|
|
assert.equal(AUTO_RUN_SNIPPET_LINE_DELAY_MS > 0, true);
|
|
assert.equal(shouldDelayAutoRunSnippetInput("tthdf 0 2323\nadmin\ntest123", { noAutoRun: false }), false);
|
|
assert.equal(
|
|
shouldDelayAutoRunSnippetInput("sudo apt install gconf2-common -y\necho \"123456\"", {
|
|
noAutoRun: false,
|
|
}),
|
|
false,
|
|
);
|
|
assert.equal(
|
|
shouldDelayAutoRunSnippetInput("tthdf 0 2323\nadmin\ntest123", {
|
|
noAutoRun: false,
|
|
multiLineRunMode: "lineDelay",
|
|
}),
|
|
true,
|
|
);
|
|
assert.equal(shouldDelayAutoRunSnippetInput("tthdf 0 2323\nadmin\ntest123", { noAutoRun: true }), false);
|
|
assert.equal(shouldDelayAutoRunSnippetInput("show version", { noAutoRun: false }), false);
|
|
assert.equal(shouldDelayAutoRunSnippetInput("show version\r", { noAutoRun: false }), false);
|
|
});
|