mirror of
https://github.com/binaricat/Netcatty.git
synced 2026-10-09 15:58:34 +00:00
214 lines
6.5 KiB
TypeScript
214 lines
6.5 KiB
TypeScript
import test from "node:test";
|
|
import assert from "node:assert/strict";
|
|
import type { Host } from "./models";
|
|
import {
|
|
buildSshDeepLinkConnectionHost,
|
|
buildSshDeepLinkHostDraft,
|
|
buildSshDeepLinkOpenHost,
|
|
buildSshNoteLinkOpenHost,
|
|
findSshDeepLinkHost,
|
|
parseSshDeepLink,
|
|
shouldHandleSshDeepLink,
|
|
} from "./sshDeepLink";
|
|
|
|
const host = (overrides: Partial<Host>): Host => ({
|
|
id: overrides.id || "host-1",
|
|
label: overrides.label || "Example",
|
|
hostname: overrides.hostname || "example.com",
|
|
username: overrides.username ?? "root",
|
|
port: overrides.port,
|
|
group: "",
|
|
tags: [],
|
|
os: "linux",
|
|
protocol: overrides.protocol ?? "ssh",
|
|
...overrides,
|
|
});
|
|
|
|
test("parseSshDeepLink accepts username host and port", () => {
|
|
assert.deepEqual(parseSshDeepLink("ssh://alice@example.com:2200"), {
|
|
rawUrl: "ssh://alice@example.com:2200",
|
|
username: "alice",
|
|
hostname: "example.com",
|
|
port: 2200,
|
|
});
|
|
});
|
|
|
|
test("parseSshDeepLink accepts IPv6 hosts", () => {
|
|
assert.deepEqual(parseSshDeepLink("ssh://bob@[2001:db8::10]:2222"), {
|
|
rawUrl: "ssh://bob@[2001:db8::10]:2222",
|
|
username: "bob",
|
|
hostname: "2001:db8::10",
|
|
port: 2222,
|
|
});
|
|
});
|
|
|
|
test("parseSshDeepLink rejects unsupported or incomplete links", () => {
|
|
assert.equal(parseSshDeepLink("https://example.com"), null);
|
|
assert.equal(parseSshDeepLink("ssh://"), null);
|
|
assert.equal(parseSshDeepLink("ssh://example.com:99999"), null);
|
|
});
|
|
|
|
test("shouldHandleSshDeepLink respects the user setting", () => {
|
|
assert.equal(shouldHandleSshDeepLink("ssh://alice@example.com", true), true);
|
|
assert.equal(shouldHandleSshDeepLink("ssh://alice@example.com", false), false);
|
|
assert.equal(shouldHandleSshDeepLink("https://example.com", true), false);
|
|
});
|
|
|
|
test("findSshDeepLinkHost matches saved ssh hosts by username hostname and port", () => {
|
|
const hosts = [
|
|
host({ id: "wrong-port", hostname: "example.com", username: "alice", port: 22 }),
|
|
host({ id: "match", hostname: "example.com", username: "alice", port: 2200 }),
|
|
host({ id: "telnet", hostname: "example.com", username: "alice", port: 2200, protocol: "telnet" }),
|
|
];
|
|
|
|
const match = findSshDeepLinkHost(hosts, parseSshDeepLink("ssh://alice@example.com:2200")!);
|
|
|
|
assert.equal(match?.id, "match");
|
|
});
|
|
|
|
test("findSshDeepLinkHost avoids ambiguous saved hosts", () => {
|
|
const hosts = [
|
|
host({ id: "one", hostname: "example.com", username: "alice", port: 2200 }),
|
|
host({ id: "two", hostname: "example.com", username: "alice", port: 2222 }),
|
|
];
|
|
|
|
const match = findSshDeepLinkHost(hosts, parseSshDeepLink("ssh://alice@example.com")!);
|
|
|
|
assert.equal(match, null);
|
|
});
|
|
|
|
test("findSshDeepLinkHost treats omitted ports as the ssh default", () => {
|
|
const hosts = [
|
|
host({ id: "custom-port", hostname: "example.com", username: "alice", port: 2200 }),
|
|
host({ id: "default-port", hostname: "example.com", username: "alice" }),
|
|
];
|
|
|
|
const match = findSshDeepLinkHost(hosts, parseSshDeepLink("ssh://alice@example.com")!);
|
|
|
|
assert.equal(match?.id, "default-port");
|
|
});
|
|
|
|
test("buildSshDeepLinkConnectionHost forces a saved host to open with ssh", () => {
|
|
const savedHost = host({
|
|
id: "saved",
|
|
hostname: "example.com",
|
|
username: "alice",
|
|
moshEnabled: true,
|
|
etEnabled: true,
|
|
});
|
|
|
|
const connectionHost = buildSshDeepLinkConnectionHost(savedHost);
|
|
|
|
assert.equal(connectionHost.protocol, "ssh");
|
|
assert.equal(connectionHost.moshEnabled, false);
|
|
assert.equal(connectionHost.etEnabled, false);
|
|
assert.equal(savedHost.moshEnabled, true);
|
|
assert.equal(savedHost.etEnabled, true);
|
|
});
|
|
|
|
test("buildSshDeepLinkHostDraft prepares an editable new ssh host", () => {
|
|
const draft = buildSshDeepLinkHostDraft(
|
|
parseSshDeepLink("ssh://alice@example.com:2200")!,
|
|
{ id: "new-id", now: 123 },
|
|
);
|
|
|
|
assert.deepEqual(draft, {
|
|
id: "new-id",
|
|
label: "alice@example.com",
|
|
hostname: "example.com",
|
|
username: "alice",
|
|
port: 2200,
|
|
group: "",
|
|
tags: [],
|
|
os: "linux",
|
|
protocol: "ssh",
|
|
createdAt: 123,
|
|
});
|
|
});
|
|
|
|
test("buildSshDeepLinkOpenHost falls back to a draft host when no saved host matches", () => {
|
|
const openHost = buildSshDeepLinkOpenHost(
|
|
[],
|
|
parseSshDeepLink("ssh://root@missing.example.com:2200")!,
|
|
{ id: "draft-id", now: 456 },
|
|
);
|
|
|
|
assert.equal(openHost.id, "draft-id");
|
|
assert.equal(openHost.hostname, "missing.example.com");
|
|
assert.equal(openHost.username, "root");
|
|
assert.equal(openHost.port, 2200);
|
|
assert.equal(openHost.protocol, "ssh");
|
|
assert.equal(openHost.moshEnabled, false);
|
|
assert.equal(openHost.etEnabled, false);
|
|
});
|
|
|
|
test("buildSshNoteLinkOpenHost opens an existing ssh link host", () => {
|
|
const openHost = buildSshNoteLinkOpenHost(
|
|
[host({ id: "match", hostname: "10.2.0.32", username: "root" })],
|
|
"ssh://10.2.0.32",
|
|
"10.2.0.32",
|
|
{ id: "draft-id", now: 456 },
|
|
);
|
|
|
|
assert.equal(openHost?.id, "match");
|
|
assert.equal(openHost?.protocol, "ssh");
|
|
assert.equal(openHost?.moshEnabled, false);
|
|
assert.equal(openHost?.etEnabled, false);
|
|
});
|
|
|
|
test("buildSshNoteLinkOpenHost treats a bare host link as an existing ssh host reference", () => {
|
|
const openHost = buildSshNoteLinkOpenHost(
|
|
[host({ id: "match", hostname: "10.2.0.32", username: "root" })],
|
|
"10.2.0.32",
|
|
"10.2.0.32",
|
|
{ id: "draft-id", now: 456 },
|
|
);
|
|
|
|
assert.equal(openHost?.id, "match");
|
|
assert.equal(openHost?.protocol, "ssh");
|
|
});
|
|
|
|
test("buildSshNoteLinkOpenHost leaves document-relative note links alone", () => {
|
|
const hosts = [
|
|
host({ id: "docs", label: "docs", hostname: "docs.example.com" }),
|
|
host({ id: "section", label: "section", hostname: "section.example.com" }),
|
|
];
|
|
|
|
for (const [href, label] of [
|
|
["/docs", "docs"],
|
|
["#section", "section"],
|
|
["./docs", "docs"],
|
|
["../docs", "docs"],
|
|
["docs/page", "docs"],
|
|
["docs?tab=install", "docs"],
|
|
["docs#install", "docs"],
|
|
] as const) {
|
|
assert.equal(
|
|
buildSshNoteLinkOpenHost(hosts, href, label, { id: "draft-id", now: 456 }),
|
|
null,
|
|
);
|
|
}
|
|
});
|
|
|
|
test("buildSshNoteLinkOpenHost does not treat sanitized editor links as hosts", () => {
|
|
const openHost = buildSshNoteLinkOpenHost(
|
|
[host({ id: "match", hostname: "10.2.0.32", username: "root" })],
|
|
"about:blank",
|
|
"10.2.0.32",
|
|
{ id: "draft-id", now: 456 },
|
|
);
|
|
|
|
assert.equal(openHost, null);
|
|
});
|
|
|
|
test("buildSshNoteLinkOpenHost ignores unrelated external links", () => {
|
|
const openHost = buildSshNoteLinkOpenHost(
|
|
[host({ id: "match", hostname: "10.2.0.32", username: "root" })],
|
|
"https://example.com",
|
|
"Example",
|
|
{ id: "draft-id", now: 456 },
|
|
);
|
|
|
|
assert.equal(openHost, null);
|
|
});
|