mirror of
https://github.com/binaricat/Netcatty.git
synced 2026-11-11 08:42:45 +00:00
* feat(ssh): opt temporary connections into network device mode Saved hosts and group-backed clones keep their own device type. SSH connections with no saved host, including external launches and quick connect, can start in network device mode when the new Terminal setting is on. The setting stays off unless the user turns it on. Co-authored-by: 陈大猫 <binaricat@users.noreply.github.com> * feat(terminal): quick connect typed addresses from the tab switcher The tab-bar quick switcher now offers the typed address when it already parses as a connection target. Choosing that row opens the existing quick connect wizard, including from a terminal tab where the vault surface is hidden. Co-authored-by: 陈大猫 <binaricat@users.noreply.github.com> * fix(ssh): keep temporary Mosh and ET off network device mode Those transports are stored as SSH plus a flag. Stamping network device mode onto them made raw-host checks skip the copy-session working directory probe. Plain temporary SSH still opts in. Co-authored-by: 陈大猫 <binaricat@users.noreply.github.com> * fix(ssh): read temporary connection settings at connect time VaultView keeps a stale onConnect callback because its memo ignores that prop. Read both temporary-connection toggles from a ref when connecting so turning them on or off applies in the same session. Co-authored-by: 陈大猫 <binaricat@users.noreply.github.com> * fix(terminal): stop word queries from opening quick connect Show the switcher quick-connect row only for address-like input, and place it after matching hosts so Enter still connects to a saved host. Translate the Hosts, Tabs, and New Workspace labels. Co-authored-by: 陈大猫 <binaricat@users.noreply.github.com> * fix(terminal): keep matching tabs ahead of quick connect An address that matches an open session or workspace was still the default Enter target when no saved host matched. Put that row after those tabs so Enter switches to the existing one. Co-authored-by: 陈大猫 <binaricat@users.noreply.github.com> --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: 陈大猫 <binaricat@users.noreply.github.com>
164 lines
4.9 KiB
TypeScript
164 lines
4.9 KiB
TypeScript
import assert from "node:assert/strict";
|
|
import test from "node:test";
|
|
import React from "react";
|
|
import { renderToStaticMarkup } from "react-dom/server";
|
|
|
|
import { I18nProvider } from "../application/i18n/I18nProvider";
|
|
import type { Host, TerminalSession } from "../types";
|
|
import { QuickSwitcher } from "./QuickSwitcher";
|
|
|
|
const host = (overrides: Partial<Host> = {}): Host => ({
|
|
id: "saved-1",
|
|
label: "core-switch",
|
|
hostname: "10.1.1.1",
|
|
username: "admin",
|
|
tags: [],
|
|
os: "linux",
|
|
protocol: "ssh",
|
|
...overrides,
|
|
}) as Host;
|
|
|
|
const renderSwitcher = (
|
|
query: string,
|
|
results: Host[] = [],
|
|
locale = "en",
|
|
) => renderToStaticMarkup(
|
|
<I18nProvider locale={locale}>
|
|
<QuickSwitcher
|
|
isOpen
|
|
query={query}
|
|
results={results}
|
|
sessions={[]}
|
|
workspaces={[]}
|
|
onQueryChange={() => undefined}
|
|
onSelect={() => undefined}
|
|
onSelectTab={() => undefined}
|
|
onClose={() => undefined}
|
|
onQuickConnect={() => undefined}
|
|
showSftpTab={false}
|
|
/>
|
|
</I18nProvider>,
|
|
);
|
|
|
|
test("quick switcher keeps a matching host ahead of an address row", () => {
|
|
const markup = renderSwitcher("10.1.1.1", [host()]);
|
|
const quickConnectAt = markup.indexOf("Quick connect to 10.1.1.1");
|
|
const hostAt = markup.indexOf("core-switch");
|
|
const selectedAt = markup.indexOf("bg-primary/15");
|
|
|
|
assert.ok(selectedAt >= 0);
|
|
assert.ok(hostAt > selectedAt);
|
|
assert.ok(quickConnectAt > hostAt);
|
|
assert.equal(markup.indexOf("bg-primary/15", selectedAt + 1), -1);
|
|
});
|
|
|
|
test("quick switcher does not steal Enter from a saved host label", () => {
|
|
for (const label of ["lab", "web01", "prod", "lab-switch"]) {
|
|
const markup = renderSwitcher(label, [host({ id: label, label, hostname: "10.0.0.5" })]);
|
|
const hostAt = markup.indexOf(`>${label}<`);
|
|
const selectedAt = markup.indexOf("bg-primary/15");
|
|
|
|
assert.equal(markup.includes("Quick connect to"), false, label);
|
|
assert.ok(selectedAt >= 0 && hostAt > selectedAt, label);
|
|
}
|
|
});
|
|
|
|
test("quick switcher keeps a matching open session ahead of an address row", () => {
|
|
const markup = renderToStaticMarkup(
|
|
<I18nProvider locale="en">
|
|
<QuickSwitcher
|
|
isOpen
|
|
query="10.4.4.4"
|
|
results={[]}
|
|
sessions={[{
|
|
id: "sess-1",
|
|
hostId: "host-1",
|
|
hostLabel: "open-core",
|
|
username: "admin",
|
|
hostname: "10.4.4.4",
|
|
status: "connected",
|
|
} as TerminalSession]}
|
|
workspaces={[]}
|
|
onQueryChange={() => undefined}
|
|
onSelect={() => undefined}
|
|
onSelectTab={() => undefined}
|
|
onClose={() => undefined}
|
|
onQuickConnect={() => undefined}
|
|
showSftpTab={false}
|
|
/>
|
|
</I18nProvider>,
|
|
);
|
|
const sessionAt = markup.indexOf("open-core");
|
|
const quickConnectAt = markup.indexOf("Quick connect to 10.4.4.4");
|
|
const selectedAt = markup.indexOf("bg-primary/15");
|
|
|
|
assert.ok(selectedAt >= 0);
|
|
assert.ok(sessionAt > selectedAt);
|
|
assert.ok(quickConnectAt > sessionAt);
|
|
assert.equal(markup.indexOf("bg-primary/15", selectedAt + 1), -1);
|
|
});
|
|
|
|
test("quick switcher offers quick connect when nothing else matches", () => {
|
|
const markup = renderSwitcher("root@10.2.0.8:2222");
|
|
|
|
assert.match(markup, /Quick connect to root@10\.2\.0\.8:2222/);
|
|
assert.match(markup, /bg-primary\/15[\s\S]*Quick connect to root@10\.2\.0\.8:2222/);
|
|
});
|
|
|
|
test("quick switcher does not offer quick connect for ordinary search text", () => {
|
|
const markup = renderSwitcher("core switch");
|
|
|
|
assert.doesNotMatch(markup, /Quick connect to/);
|
|
});
|
|
|
|
test("quick switcher quick connect row uses zh-TW wording", () => {
|
|
const markup = renderToStaticMarkup(
|
|
<I18nProvider locale="zh-TW">
|
|
<QuickSwitcher
|
|
isOpen
|
|
query="10.0.0.8"
|
|
results={[host()]}
|
|
sessions={[]}
|
|
workspaces={[]}
|
|
onQueryChange={() => undefined}
|
|
onSelect={() => undefined}
|
|
onSelectTab={() => undefined}
|
|
onClose={() => undefined}
|
|
onQuickConnect={() => undefined}
|
|
onCreateWorkspace={() => undefined}
|
|
showSftpTab={false}
|
|
/>
|
|
</I18nProvider>,
|
|
);
|
|
|
|
assert.match(markup, /快速連線到 10\.0\.0\.8/);
|
|
assert.match(markup, />主機</);
|
|
assert.match(markup, />新增工作區</);
|
|
assert.doesNotMatch(markup, /New Workspace/);
|
|
});
|
|
|
|
test("quick switcher section labels use zh-CN wording", () => {
|
|
const markup = renderToStaticMarkup(
|
|
<I18nProvider locale="zh-CN">
|
|
<QuickSwitcher
|
|
isOpen
|
|
query=""
|
|
results={[host()]}
|
|
sessions={[]}
|
|
workspaces={[]}
|
|
onQueryChange={() => undefined}
|
|
onSelect={() => undefined}
|
|
onSelectTab={() => undefined}
|
|
onClose={() => undefined}
|
|
onQuickConnect={() => undefined}
|
|
onCreateWorkspace={() => undefined}
|
|
showSftpTab={false}
|
|
/>
|
|
</I18nProvider>,
|
|
);
|
|
|
|
assert.match(markup, />主机</);
|
|
assert.match(markup, />标签页</);
|
|
assert.match(markup, />新建工作区</);
|
|
});
|