summaryrefslogtreecommitdiffhomepage
path: root/packages/ssh/src/config.test.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/ssh/src/config.test.ts')
-rw-r--r--packages/ssh/src/config.test.ts650
1 files changed, 325 insertions, 325 deletions
diff --git a/packages/ssh/src/config.test.ts b/packages/ssh/src/config.test.ts
index 04ccdc5..a54f8d6 100644
--- a/packages/ssh/src/config.test.ts
+++ b/packages/ssh/src/config.test.ts
@@ -1,19 +1,19 @@
import { describe, expect, it } from "vitest";
import {
- isRejected,
- knownHostToken,
- parseKnownHosts,
- resolveComputer,
- resolveComputers,
- type SshConfigResolveEnv,
+ isRejected,
+ knownHostToken,
+ parseKnownHosts,
+ resolveComputer,
+ resolveComputers,
+ type SshConfigResolveEnv,
} from "./config.js";
const env = (overrides: Partial<SshConfigResolveEnv> = {}): SshConfigResolveEnv => ({
- configText: "",
- knownHostsText: "",
- defaultUser: "fallback-user",
- homeDir: "/home/test",
- ...overrides,
+ configText: "",
+ knownHostsText: "",
+ defaultUser: "fallback-user",
+ homeDir: "/home/test",
+ ...overrides,
});
const FIXTURE = `
@@ -41,376 +41,376 @@ Host github.com
`;
describe("resolveComputers", () => {
- it("returns one Computer per named (non-wildcard) Host alias, sorted", () => {
- const computers = resolveComputers(env({ configText: FIXTURE }));
- expect(computers.map((c) => c.alias)).toEqual(["barehost", "github.com", "myserver", "web"]);
- });
-
- it("skips wildcard-only Host patterns (* and ?)", () => {
- const computers = resolveComputers(env({ configText: FIXTURE }));
- // The bare `*` host is a pattern, not a computer — excluded.
- expect(computers.find((c) => c.alias === "*")).toBeUndefined();
- });
-
- it("skips wildcard aliases within a multi-alias Host line (*.example.com)", () => {
- const computers = resolveComputers(env({ configText: FIXTURE }));
- expect(computers.find((c) => c.alias === "*.example.com")).toBeUndefined();
- // but the named alias on the SAME line (web) is included.
- expect(computers.find((c) => c.alias === "web")).toBeDefined();
- });
-
- it("resolves HostName/Port/User/IdentityFile from the config (first-match-wins)", () => {
- const computers = resolveComputers(env({ configText: FIXTURE }));
- const my = computers.find((c) => c.alias === "myserver");
- expect(my).toEqual({
- alias: "myserver",
- hostName: "10.0.0.5",
- port: 2222,
- user: "deploy",
- identityFile: "/home/test/.ssh/deploy_key",
- knownHost: false,
- });
- });
-
- it("falls back HostName → alias when no HostName is set", () => {
- const computers = resolveComputers(env({ configText: FIXTURE }));
- const bare = computers.find((c) => c.alias === "barehost");
- expect(bare?.hostName).toBe("barehost");
- expect(bare?.port).toBe(22);
- expect(bare?.user).toBe("fallback-user");
- expect(bare?.identityFile).toBeNull();
- });
-
- it("expands ~ in IdentityFile to homeDir", () => {
- const computers = resolveComputers(env({ configText: FIXTURE }));
- const gh = computers.find((c) => c.alias === "github.com");
- expect(gh?.identityFile).toBe("/home/test/.ssh/github_key");
- });
-
- it("resolves a Host block whose first alias is a wildcard but later alias is named", () => {
- const computers = resolveComputers(env({ configText: FIXTURE }));
- const web = computers.find((c) => c.alias === "web");
- expect(web?.hostName).toBe("web.internal");
- expect(web?.user).toBe("webuser");
- });
-
- it("de-dups aliases listed in multiple Host lines (first wins)", () => {
- const dup = `
+ it("returns one Computer per named (non-wildcard) Host alias, sorted", () => {
+ const computers = resolveComputers(env({ configText: FIXTURE }));
+ expect(computers.map((c) => c.alias)).toEqual(["barehost", "github.com", "myserver", "web"]);
+ });
+
+ it("skips wildcard-only Host patterns (* and ?)", () => {
+ const computers = resolveComputers(env({ configText: FIXTURE }));
+ // The bare `*` host is a pattern, not a computer — excluded.
+ expect(computers.find((c) => c.alias === "*")).toBeUndefined();
+ });
+
+ it("skips wildcard aliases within a multi-alias Host line (*.example.com)", () => {
+ const computers = resolveComputers(env({ configText: FIXTURE }));
+ expect(computers.find((c) => c.alias === "*.example.com")).toBeUndefined();
+ // but the named alias on the SAME line (web) is included.
+ expect(computers.find((c) => c.alias === "web")).toBeDefined();
+ });
+
+ it("resolves HostName/Port/User/IdentityFile from the config (first-match-wins)", () => {
+ const computers = resolveComputers(env({ configText: FIXTURE }));
+ const my = computers.find((c) => c.alias === "myserver");
+ expect(my).toEqual({
+ alias: "myserver",
+ hostName: "10.0.0.5",
+ port: 2222,
+ user: "deploy",
+ identityFile: "/home/test/.ssh/deploy_key",
+ knownHost: false,
+ });
+ });
+
+ it("falls back HostName → alias when no HostName is set", () => {
+ const computers = resolveComputers(env({ configText: FIXTURE }));
+ const bare = computers.find((c) => c.alias === "barehost");
+ expect(bare?.hostName).toBe("barehost");
+ expect(bare?.port).toBe(22);
+ expect(bare?.user).toBe("fallback-user");
+ expect(bare?.identityFile).toBeNull();
+ });
+
+ it("expands ~ in IdentityFile to homeDir", () => {
+ const computers = resolveComputers(env({ configText: FIXTURE }));
+ const gh = computers.find((c) => c.alias === "github.com");
+ expect(gh?.identityFile).toBe("/home/test/.ssh/github_key");
+ });
+
+ it("resolves a Host block whose first alias is a wildcard but later alias is named", () => {
+ const computers = resolveComputers(env({ configText: FIXTURE }));
+ const web = computers.find((c) => c.alias === "web");
+ expect(web?.hostName).toBe("web.internal");
+ expect(web?.user).toBe("webuser");
+ });
+
+ it("de-dups aliases listed in multiple Host lines (first wins)", () => {
+ const dup = `
Host dup
HostName first.example
Host dup
HostName second.example
`;
- const computers = resolveComputers(env({ configText: dup }));
- expect(computers).toHaveLength(1);
- expect(computers[0]?.hostName).toBe("first.example");
- });
-
- it("knownHost=true when the resolved HostName:port token is in known_hosts", () => {
- // myserver is port 2222 → token is [10.0.0.5]:2222; web is port 22 → bare host.
- const known = "[10.0.0.5]:2222 ssh-ed25519 AAA\nweb.internal ssh-ed25519 BBB\n";
- const computers = resolveComputers(env({ configText: FIXTURE, knownHostsText: known }));
- expect(computers.find((c) => c.alias === "myserver")?.knownHost).toBe(true);
- // default port 22 → token is just the hostName (no bracket).
- expect(computers.find((c) => c.alias === "web")?.knownHost).toBe(true);
- expect(computers.find((c) => c.alias === "barehost")?.knownHost).toBe(false);
- });
-
- it("knownHost keys a non-default port as [host]:port", () => {
- const known = "[10.0.0.5]:2222 ssh-ed25519 AAA\n";
- const computers = resolveComputers(env({ configText: FIXTURE, knownHostsText: known }));
- expect(computers.find((c) => c.alias === "myserver")?.knownHost).toBe(true);
- });
+ const computers = resolveComputers(env({ configText: dup }));
+ expect(computers).toHaveLength(1);
+ expect(computers[0]?.hostName).toBe("first.example");
+ });
+
+ it("knownHost=true when the resolved HostName:port token is in known_hosts", () => {
+ // myserver is port 2222 → token is [10.0.0.5]:2222; web is port 22 → bare host.
+ const known = "[10.0.0.5]:2222 ssh-ed25519 AAA\nweb.internal ssh-ed25519 BBB\n";
+ const computers = resolveComputers(env({ configText: FIXTURE, knownHostsText: known }));
+ expect(computers.find((c) => c.alias === "myserver")?.knownHost).toBe(true);
+ // default port 22 → token is just the hostName (no bracket).
+ expect(computers.find((c) => c.alias === "web")?.knownHost).toBe(true);
+ expect(computers.find((c) => c.alias === "barehost")?.knownHost).toBe(false);
+ });
+
+ it("knownHost keys a non-default port as [host]:port", () => {
+ const known = "[10.0.0.5]:2222 ssh-ed25519 AAA\n";
+ const computers = resolveComputers(env({ configText: FIXTURE, knownHostsText: known }));
+ expect(computers.find((c) => c.alias === "myserver")?.knownHost).toBe(true);
+ });
});
describe("resolveComputer (single alias)", () => {
- it("resolves a named alias", () => {
- const c = resolveComputer("myserver", env({ configText: FIXTURE }));
- expect(c?.hostName).toBe("10.0.0.5");
- expect(c?.port).toBe(2222);
- });
-
- it("returns null for an unknown alias", () => {
- expect(resolveComputer("nope", env({ configText: FIXTURE }))).toBeNull();
- });
-
- it("returns null for a wildcard alias (not a selectable computer)", () => {
- expect(resolveComputer("*.example.com", env({ configText: FIXTURE }))).toBeNull();
- });
-
- it("applies top-level wildcard defaults to a named host (first-match-wins)", () => {
- const cfg = `
+ it("resolves a named alias", () => {
+ const c = resolveComputer("myserver", env({ configText: FIXTURE }));
+ expect(c?.hostName).toBe("10.0.0.5");
+ expect(c?.port).toBe(2222);
+ });
+
+ it("returns null for an unknown alias", () => {
+ expect(resolveComputer("nope", env({ configText: FIXTURE }))).toBeNull();
+ });
+
+ it("returns null for a wildcard alias (not a selectable computer)", () => {
+ expect(resolveComputer("*.example.com", env({ configText: FIXTURE }))).toBeNull();
+ });
+
+ it("applies top-level wildcard defaults to a named host (first-match-wins)", () => {
+ const cfg = `
Host *
ServerAliveInterval 60
User stardefault
Host named
HostName named.example
`;
- const c = resolveComputer("named", env({ configText: cfg }));
- // User inherited from the `Host *` block via first-match-wins.
- expect(c?.user).toBe("stardefault");
- expect(c?.hostName).toBe("named.example");
- });
+ const c = resolveComputer("named", env({ configText: cfg }));
+ // User inherited from the `Host *` block via first-match-wins.
+ expect(c?.user).toBe("stardefault");
+ expect(c?.hostName).toBe("named.example");
+ });
});
describe("knownHostToken", () => {
- it("returns the bare host for the default port (22)", () => {
- expect(knownHostToken("host.example", 22)).toBe("host.example");
- });
+ it("returns the bare host for the default port (22)", () => {
+ expect(knownHostToken("host.example", 22)).toBe("host.example");
+ });
- it("returns [host]:port for a non-default port", () => {
- expect(knownHostToken("host.example", 2222)).toBe("[host.example]:2222");
- });
+ it("returns [host]:port for a non-default port", () => {
+ expect(knownHostToken("host.example", 2222)).toBe("[host.example]:2222");
+ });
});
// ─── known_hosts discovery ─────────────────────────────────────────────────
const KNOWN_HOSTS_FIXTURE = [
- "# comment line",
- "arch-razer ssh-ed25519 AAAA1",
- "xenifse1 ssh-ed25519 AAAA2",
- "xenifse1 ssh-rsa AAAA3",
- "xenifse1 ecdsa-sha2-nistp256 AAAA4",
- "[xenifse1]:2222 ssh-ed25519 AAAA5",
- "github.com ssh-ed25519 AAAA6",
- "|1|+W4/jC7U8rJwiEC2m0KvG2A7uAA=|rWwV8p5J1FfR3k= ssh-ed25519 AAAA7",
- "localhost ssh-ed25519 AAAA8",
- "[localhost]:2222 ssh-ed25519 AAAA9",
+ "# comment line",
+ "arch-razer ssh-ed25519 AAAA1",
+ "xenifse1 ssh-ed25519 AAAA2",
+ "xenifse1 ssh-rsa AAAA3",
+ "xenifse1 ecdsa-sha2-nistp256 AAAA4",
+ "[xenifse1]:2222 ssh-ed25519 AAAA5",
+ "github.com ssh-ed25519 AAAA6",
+ "|1|+W4/jC7U8rJwiEC2m0KvG2A7uAA=|rWwV8p5J1FfR3k= ssh-ed25519 AAAA7",
+ "localhost ssh-ed25519 AAAA8",
+ "[localhost]:2222 ssh-ed25519 AAAA9",
].join("\n");
describe("parseKnownHosts", () => {
- it("extracts hostnames with default port 22 from bare entries", () => {
- const entries = parseKnownHosts(KNOWN_HOSTS_FIXTURE);
- const arch = entries.find((e) => e.hostname === "arch-razer");
- expect(arch).toEqual({ hostname: "arch-razer", port: 22 });
- });
-
- it("extracts hostname + port from [host]:port notation", () => {
- const entries = parseKnownHosts(KNOWN_HOSTS_FIXTURE);
- // xenifse1 has entries on port 22 (first) and port 2222 — first wins.
- const xen = entries.find((e) => e.hostname === "xenifse1");
- expect(xen?.port).toBe(22);
- // localhost appears as port 22 (first) and [localhost]:2222 — first wins.
- const local = entries.find((e) => e.hostname === "localhost");
- expect(local?.port).toBe(22);
- });
-
- it("deduplicates by hostname (first port wins)", () => {
- const entries = parseKnownHosts(KNOWN_HOSTS_FIXTURE);
- const xenCount = entries.filter((e) => e.hostname === "xenifse1").length;
- expect(xenCount).toBe(1);
- // Multiple key types (ed25519, rsa, ecdsa) for the same host:port = 1 entry.
- expect(entries).toHaveLength(4); // arch-razer, xenifse1, github.com, localhost
- });
-
- it("skips hashed entries (|1|...)", () => {
- const entries = parseKnownHosts(KNOWN_HOSTS_FIXTURE);
- expect(entries.find((e) => e.hostname.startsWith("|"))).toBeUndefined();
- });
-
- it("skips comment lines and empty lines", () => {
- const entries = parseKnownHosts("\n# comment\n\n \nhost1 ssh-ed25519 AAA\n");
- expect(entries).toHaveLength(1);
- expect(entries[0]?.hostname).toBe("host1");
- });
-
- it("returns empty for empty text", () => {
- expect(parseKnownHosts("")).toEqual([]);
- expect(parseKnownHosts(" \n\n ")).toEqual([]);
- });
-
- it("handles comma-separated host markers", () => {
- const entries = parseKnownHosts("hostA,hostB ssh-ed25519 AAA\n");
- expect(entries.map((e) => e.hostname)).toEqual(["hostA", "hostB"]);
- });
-
- it("preserves non-default port when the host only has [host]:port entries", () => {
- const entries = parseKnownHosts("[specialhost]:9999 ssh-ed25519 AAA\n");
- expect(entries[0]).toEqual({ hostname: "specialhost", port: 9999 });
- });
+ it("extracts hostnames with default port 22 from bare entries", () => {
+ const entries = parseKnownHosts(KNOWN_HOSTS_FIXTURE);
+ const arch = entries.find((e) => e.hostname === "arch-razer");
+ expect(arch).toEqual({ hostname: "arch-razer", port: 22 });
+ });
+
+ it("extracts hostname + port from [host]:port notation", () => {
+ const entries = parseKnownHosts(KNOWN_HOSTS_FIXTURE);
+ // xenifse1 has entries on port 22 (first) and port 2222 — first wins.
+ const xen = entries.find((e) => e.hostname === "xenifse1");
+ expect(xen?.port).toBe(22);
+ // localhost appears as port 22 (first) and [localhost]:2222 — first wins.
+ const local = entries.find((e) => e.hostname === "localhost");
+ expect(local?.port).toBe(22);
+ });
+
+ it("deduplicates by hostname (first port wins)", () => {
+ const entries = parseKnownHosts(KNOWN_HOSTS_FIXTURE);
+ const xenCount = entries.filter((e) => e.hostname === "xenifse1").length;
+ expect(xenCount).toBe(1);
+ // Multiple key types (ed25519, rsa, ecdsa) for the same host:port = 1 entry.
+ expect(entries).toHaveLength(4); // arch-razer, xenifse1, github.com, localhost
+ });
+
+ it("skips hashed entries (|1|...)", () => {
+ const entries = parseKnownHosts(KNOWN_HOSTS_FIXTURE);
+ expect(entries.find((e) => e.hostname.startsWith("|"))).toBeUndefined();
+ });
+
+ it("skips comment lines and empty lines", () => {
+ const entries = parseKnownHosts("\n# comment\n\n \nhost1 ssh-ed25519 AAA\n");
+ expect(entries).toHaveLength(1);
+ expect(entries[0]?.hostname).toBe("host1");
+ });
+
+ it("returns empty for empty text", () => {
+ expect(parseKnownHosts("")).toEqual([]);
+ expect(parseKnownHosts(" \n\n ")).toEqual([]);
+ });
+
+ it("handles comma-separated host markers", () => {
+ const entries = parseKnownHosts("hostA,hostB ssh-ed25519 AAA\n");
+ expect(entries.map((e) => e.hostname)).toEqual(["hostA", "hostB"]);
+ });
+
+ it("preserves non-default port when the host only has [host]:port entries", () => {
+ const entries = parseKnownHosts("[specialhost]:9999 ssh-ed25519 AAA\n");
+ expect(entries[0]).toEqual({ hostname: "specialhost", port: 9999 });
+ });
});
// ─── known_hosts discovery merged into resolveComputers ───────────────────
describe("resolveComputers with known_hosts discovery", () => {
- it("discovers computers from known_hosts when no ~/.ssh/config exists", () => {
- const computers = resolveComputers(env({ knownHostsText: KNOWN_HOSTS_FIXTURE }));
- const aliases = computers.map((c) => c.alias);
- expect(aliases).toContain("arch-razer");
- expect(aliases).toContain("xenifse1");
- expect(aliases).toContain("github.com");
- expect(aliases).toContain("localhost");
- });
-
- it("defaulted params for known_hosts-discovered computers", () => {
- const computers = resolveComputers(env({ knownHostsText: KNOWN_HOSTS_FIXTURE }));
- const arch = computers.find((c) => c.alias === "arch-razer");
- expect(arch).toEqual({
- alias: "arch-razer",
- hostName: "arch-razer",
- port: 22,
- user: "fallback-user",
- identityFile: null,
- knownHost: true,
- });
- });
-
- it("config entries take precedence over known_hosts (no duplication)", () => {
- const cfg = `
+ it("discovers computers from known_hosts when no ~/.ssh/config exists", () => {
+ const computers = resolveComputers(env({ knownHostsText: KNOWN_HOSTS_FIXTURE }));
+ const aliases = computers.map((c) => c.alias);
+ expect(aliases).toContain("arch-razer");
+ expect(aliases).toContain("xenifse1");
+ expect(aliases).toContain("github.com");
+ expect(aliases).toContain("localhost");
+ });
+
+ it("defaulted params for known_hosts-discovered computers", () => {
+ const computers = resolveComputers(env({ knownHostsText: KNOWN_HOSTS_FIXTURE }));
+ const arch = computers.find((c) => c.alias === "arch-razer");
+ expect(arch).toEqual({
+ alias: "arch-razer",
+ hostName: "arch-razer",
+ port: 22,
+ user: "fallback-user",
+ identityFile: null,
+ knownHost: true,
+ });
+ });
+
+ it("config entries take precedence over known_hosts (no duplication)", () => {
+ const cfg = `
Host arch-razer
HostName 192.168.1.100
User root
Port 2222
`;
- const computers = resolveComputers(
- env({ configText: cfg, knownHostsText: KNOWN_HOSTS_FIXTURE }),
- );
- const arch = computers.filter((c) => c.alias === "arch-razer");
- expect(arch).toHaveLength(1);
- // Config params win, not the known_hosts defaults.
- expect(arch[0]?.hostName).toBe("192.168.1.100");
- expect(arch[0]?.user).toBe("root");
- expect(arch[0]?.port).toBe(2222);
- });
-
- it("merges config + known_hosts entries (union, sorted)", () => {
- const cfg = `
+ const computers = resolveComputers(
+ env({ configText: cfg, knownHostsText: KNOWN_HOSTS_FIXTURE }),
+ );
+ const arch = computers.filter((c) => c.alias === "arch-razer");
+ expect(arch).toHaveLength(1);
+ // Config params win, not the known_hosts defaults.
+ expect(arch[0]?.hostName).toBe("192.168.1.100");
+ expect(arch[0]?.user).toBe("root");
+ expect(arch[0]?.port).toBe(2222);
+ });
+
+ it("merges config + known_hosts entries (union, sorted)", () => {
+ const cfg = `
Host server-a
HostName 10.0.0.1
`;
- const computers = resolveComputers(
- env({ configText: cfg, knownHostsText: KNOWN_HOSTS_FIXTURE }),
- );
- const aliases = computers.map((c) => c.alias);
- // config entry + known_hosts entries, all unique, sorted.
- expect(aliases).toEqual(["arch-razer", "github.com", "localhost", "server-a", "xenifse1"]);
- });
+ const computers = resolveComputers(
+ env({ configText: cfg, knownHostsText: KNOWN_HOSTS_FIXTURE }),
+ );
+ const aliases = computers.map((c) => c.alias);
+ // config entry + known_hosts entries, all unique, sorted.
+ expect(aliases).toEqual(["arch-razer", "github.com", "localhost", "server-a", "xenifse1"]);
+ });
});
// ─── reject-list filtering ────────────────────────────────────────────────
describe("resolveComputers with rejectPatterns", () => {
- it("filters out exact-match rejected hostnames", () => {
- const computers = resolveComputers(
- env({
- knownHostsText: KNOWN_HOSTS_FIXTURE,
- rejectPatterns: ["github.com"],
- }),
- );
- expect(computers.find((c) => c.alias === "github.com")).toBeUndefined();
- expect(computers.find((c) => c.alias === "arch-razer")).toBeDefined();
- });
-
- it("filters out glob patterns (* matches any sequence)", () => {
- const computers = resolveComputers(
- env({
- knownHostsText: KNOWN_HOSTS_FIXTURE,
- rejectPatterns: ["*.com"],
- }),
- );
- expect(computers.find((c) => c.alias === "github.com")).toBeUndefined();
- expect(computers.find((c) => c.alias === "arch-razer")).toBeDefined();
- });
-
- it("filters multiple patterns", () => {
- const computers = resolveComputers(
- env({
- knownHostsText: KNOWN_HOSTS_FIXTURE,
- rejectPatterns: ["github.com", "localhost"],
- }),
- );
- const aliases = computers.map((c) => c.alias);
- expect(aliases).toEqual(["arch-razer", "xenifse1"]);
- });
-
- it("does NOT filter resolveComputer (single alias lookup ignores reject list)", () => {
- // resolveComputer is for specific lookups (status, test, connect) —
- // the reject list is a discovery/catalog filter, not access control.
- const c = resolveComputer(
- "github.com",
- env({ knownHostsText: KNOWN_HOSTS_FIXTURE, rejectPatterns: ["github.com"] }),
- );
- expect(c).not.toBeNull();
- expect(c?.alias).toBe("github.com");
- });
-
- it("empty rejectPatterns does not filter anything", () => {
- const computers = resolveComputers(
- env({ knownHostsText: KNOWN_HOSTS_FIXTURE, rejectPatterns: [] }),
- );
- expect(computers).toHaveLength(4);
- });
-
- it("absent rejectPatterns does not filter anything", () => {
- const computers = resolveComputers(env({ knownHostsText: KNOWN_HOSTS_FIXTURE }));
- expect(computers).toHaveLength(4);
- });
+ it("filters out exact-match rejected hostnames", () => {
+ const computers = resolveComputers(
+ env({
+ knownHostsText: KNOWN_HOSTS_FIXTURE,
+ rejectPatterns: ["github.com"],
+ }),
+ );
+ expect(computers.find((c) => c.alias === "github.com")).toBeUndefined();
+ expect(computers.find((c) => c.alias === "arch-razer")).toBeDefined();
+ });
+
+ it("filters out glob patterns (* matches any sequence)", () => {
+ const computers = resolveComputers(
+ env({
+ knownHostsText: KNOWN_HOSTS_FIXTURE,
+ rejectPatterns: ["*.com"],
+ }),
+ );
+ expect(computers.find((c) => c.alias === "github.com")).toBeUndefined();
+ expect(computers.find((c) => c.alias === "arch-razer")).toBeDefined();
+ });
+
+ it("filters multiple patterns", () => {
+ const computers = resolveComputers(
+ env({
+ knownHostsText: KNOWN_HOSTS_FIXTURE,
+ rejectPatterns: ["github.com", "localhost"],
+ }),
+ );
+ const aliases = computers.map((c) => c.alias);
+ expect(aliases).toEqual(["arch-razer", "xenifse1"]);
+ });
+
+ it("does NOT filter resolveComputer (single alias lookup ignores reject list)", () => {
+ // resolveComputer is for specific lookups (status, test, connect) —
+ // the reject list is a discovery/catalog filter, not access control.
+ const c = resolveComputer(
+ "github.com",
+ env({ knownHostsText: KNOWN_HOSTS_FIXTURE, rejectPatterns: ["github.com"] }),
+ );
+ expect(c).not.toBeNull();
+ expect(c?.alias).toBe("github.com");
+ });
+
+ it("empty rejectPatterns does not filter anything", () => {
+ const computers = resolveComputers(
+ env({ knownHostsText: KNOWN_HOSTS_FIXTURE, rejectPatterns: [] }),
+ );
+ expect(computers).toHaveLength(4);
+ });
+
+ it("absent rejectPatterns does not filter anything", () => {
+ const computers = resolveComputers(env({ knownHostsText: KNOWN_HOSTS_FIXTURE }));
+ expect(computers).toHaveLength(4);
+ });
});
// ─── resolveComputer known_hosts fallback ─────────────────────────────────
describe("resolveComputer with known_hosts fallback", () => {
- it("resolves a host from known_hosts when not in config", () => {
- const c = resolveComputer("arch-razer", env({ knownHostsText: KNOWN_HOSTS_FIXTURE }));
- expect(c).toEqual({
- alias: "arch-razer",
- hostName: "arch-razer",
- port: 22,
- user: "fallback-user",
- identityFile: null,
- knownHost: true,
- });
- });
-
- it("returns null for a host in neither config nor known_hosts", () => {
- const c = resolveComputer("nonexistent", env({ knownHostsText: KNOWN_HOSTS_FIXTURE }));
- expect(c).toBeNull();
- });
-
- it("config takes precedence over known_hosts for resolveComputer", () => {
- const cfg = `
+ it("resolves a host from known_hosts when not in config", () => {
+ const c = resolveComputer("arch-razer", env({ knownHostsText: KNOWN_HOSTS_FIXTURE }));
+ expect(c).toEqual({
+ alias: "arch-razer",
+ hostName: "arch-razer",
+ port: 22,
+ user: "fallback-user",
+ identityFile: null,
+ knownHost: true,
+ });
+ });
+
+ it("returns null for a host in neither config nor known_hosts", () => {
+ const c = resolveComputer("nonexistent", env({ knownHostsText: KNOWN_HOSTS_FIXTURE }));
+ expect(c).toBeNull();
+ });
+
+ it("config takes precedence over known_hosts for resolveComputer", () => {
+ const cfg = `
Host arch-razer
HostName 192.168.1.100
User root
`;
- const c = resolveComputer(
- "arch-razer",
- env({ configText: cfg, knownHostsText: KNOWN_HOSTS_FIXTURE }),
- );
- expect(c?.hostName).toBe("192.168.1.100");
- expect(c?.user).toBe("root");
- });
+ const c = resolveComputer(
+ "arch-razer",
+ env({ configText: cfg, knownHostsText: KNOWN_HOSTS_FIXTURE }),
+ );
+ expect(c?.hostName).toBe("192.168.1.100");
+ expect(c?.user).toBe("root");
+ });
});
// ─── isRejected glob matching ──────────────────────────────────────────────
describe("isRejected", () => {
- it("matches exact hostname", () => {
- expect(isRejected("github.com", ["github.com"])).toBe(true);
- expect(isRejected("arch-razer", ["github.com"])).toBe(false);
- });
-
- it("matches * glob (any sequence)", () => {
- expect(isRejected("foo.ts.net", ["*.ts.net"])).toBe(true);
- // * matches zero chars, but the remaining ".ts.net" (with literal dot)
- // still doesn't match "ts.net" — the dot is required.
- expect(isRejected("ts.net", ["*.ts.net"])).toBe(false);
- expect(isRejected("foo.other.net", ["*.ts.net"])).toBe(false);
- });
-
- it("matches ? glob (single char)", () => {
- expect(isRejected("host1", ["host?"])).toBe(true);
- expect(isRejected("host12", ["host?"])).toBe(false); // ? = exactly one char
- });
-
- it("is case-insensitive", () => {
- expect(isRejected("GitHub.Com", ["github.com"])).toBe(true);
- expect(isRejected("FOO.TS.NET", ["*.ts.net"])).toBe(true);
- });
-
- it("returns false for absent or empty patterns", () => {
- expect(isRejected("anything")).toBe(false);
- expect(isRejected("anything", [])).toBe(false);
- expect(isRejected("anything", undefined)).toBe(false);
- });
+ it("matches exact hostname", () => {
+ expect(isRejected("github.com", ["github.com"])).toBe(true);
+ expect(isRejected("arch-razer", ["github.com"])).toBe(false);
+ });
+
+ it("matches * glob (any sequence)", () => {
+ expect(isRejected("foo.ts.net", ["*.ts.net"])).toBe(true);
+ // * matches zero chars, but the remaining ".ts.net" (with literal dot)
+ // still doesn't match "ts.net" — the dot is required.
+ expect(isRejected("ts.net", ["*.ts.net"])).toBe(false);
+ expect(isRejected("foo.other.net", ["*.ts.net"])).toBe(false);
+ });
+
+ it("matches ? glob (single char)", () => {
+ expect(isRejected("host1", ["host?"])).toBe(true);
+ expect(isRejected("host12", ["host?"])).toBe(false); // ? = exactly one char
+ });
+
+ it("is case-insensitive", () => {
+ expect(isRejected("GitHub.Com", ["github.com"])).toBe(true);
+ expect(isRejected("FOO.TS.NET", ["*.ts.net"])).toBe(true);
+ });
+
+ it("returns false for absent or empty patterns", () => {
+ expect(isRejected("anything")).toBe(false);
+ expect(isRejected("anything", [])).toBe(false);
+ expect(isRejected("anything", undefined)).toBe(false);
+ });
});