mirror of
https://github.com/Termix-SSH/Termix.git
synced 2026-07-17 05:43:36 +00:00
125 lines
3.7 KiB
TypeScript
125 lines
3.7 KiB
TypeScript
import type { Client } from "ssh2";
|
|
import { describe, it, expect, vi } from "vitest";
|
|
import {
|
|
supportsMetrics,
|
|
isTcpPingEnabled,
|
|
createConnectionLog,
|
|
tcpPingThroughJumpHost,
|
|
} from "./host-metrics-helpers.js";
|
|
|
|
describe("supportsMetrics", () => {
|
|
it("supports plain ssh hosts", () => {
|
|
expect(
|
|
supportsMetrics({ connectionType: "ssh", authType: "password" }),
|
|
).toBe(true);
|
|
});
|
|
|
|
it("defaults missing connectionType to ssh", () => {
|
|
expect(supportsMetrics({ authType: "key" })).toBe(true);
|
|
});
|
|
|
|
it("rejects non-ssh connection types", () => {
|
|
expect(supportsMetrics({ connectionType: "rdp" })).toBe(false);
|
|
expect(supportsMetrics({ connectionType: "vnc" })).toBe(false);
|
|
expect(supportsMetrics({ connectionType: "telnet" })).toBe(false);
|
|
});
|
|
|
|
it("rejects ssh hosts that cannot run shell commands", () => {
|
|
expect(supportsMetrics({ connectionType: "ssh", authType: "none" })).toBe(
|
|
false,
|
|
);
|
|
expect(supportsMetrics({ connectionType: "ssh", authType: "opkssh" })).toBe(
|
|
false,
|
|
);
|
|
});
|
|
});
|
|
|
|
describe("isTcpPingEnabled", () => {
|
|
it("is enabled when status checks are on and tcp ping is not disabled", () => {
|
|
expect(
|
|
isTcpPingEnabled({ statusCheckEnabled: true, disableTcpPing: false }),
|
|
).toBe(true);
|
|
expect(isTcpPingEnabled({ statusCheckEnabled: true })).toBe(true);
|
|
});
|
|
|
|
it("is disabled when status checks are off", () => {
|
|
expect(isTcpPingEnabled({ statusCheckEnabled: false })).toBe(false);
|
|
});
|
|
|
|
it("is disabled when tcp ping is explicitly disabled", () => {
|
|
expect(
|
|
isTcpPingEnabled({ statusCheckEnabled: true, disableTcpPing: true }),
|
|
).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe("createConnectionLog", () => {
|
|
it("builds a log entry without id/timestamp", () => {
|
|
const entry = createConnectionLog("info", "connection", "Connecting", {
|
|
hostId: 1,
|
|
});
|
|
expect(entry).toEqual({
|
|
type: "info",
|
|
stage: "connection",
|
|
message: "Connecting",
|
|
details: { hostId: 1 },
|
|
});
|
|
expect("id" in entry).toBe(false);
|
|
expect("timestamp" in entry).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe("tcpPingThroughJumpHost", () => {
|
|
it("reports the final destination online when forwarding succeeds", async () => {
|
|
const stream = { destroy: vi.fn() };
|
|
const jumpClient = {
|
|
end: vi.fn(),
|
|
forwardOut: vi.fn((_src, _srcPort, host, port, callback) => {
|
|
expect(host).toBe("private.example");
|
|
expect(port).toBe(22);
|
|
callback(undefined, stream);
|
|
}),
|
|
} as unknown as Pick<Client, "forwardOut" | "end">;
|
|
|
|
await expect(
|
|
tcpPingThroughJumpHost(jumpClient, "private.example", 22),
|
|
).resolves.toBe(true);
|
|
expect(stream.destroy).toHaveBeenCalledOnce();
|
|
expect(jumpClient.end).toHaveBeenCalledOnce();
|
|
});
|
|
|
|
it("reports the final destination offline when forwarding fails", async () => {
|
|
const jumpClient = {
|
|
end: vi.fn(),
|
|
forwardOut: vi.fn((_src, _srcPort, _host, _port, callback) => {
|
|
callback(new Error("Connection refused"));
|
|
}),
|
|
} as unknown as Pick<Client, "forwardOut" | "end">;
|
|
|
|
await expect(
|
|
tcpPingThroughJumpHost(jumpClient, "private.example", 22),
|
|
).resolves.toBe(false);
|
|
expect(jumpClient.end).toHaveBeenCalledOnce();
|
|
});
|
|
|
|
it("reports the final destination offline when forwarding times out", async () => {
|
|
vi.useFakeTimers();
|
|
const jumpClient = {
|
|
end: vi.fn(),
|
|
forwardOut: vi.fn(),
|
|
} as unknown as Pick<Client, "forwardOut" | "end">;
|
|
|
|
const result = tcpPingThroughJumpHost(
|
|
jumpClient,
|
|
"private.example",
|
|
22,
|
|
5000,
|
|
);
|
|
await vi.advanceTimersByTimeAsync(5000);
|
|
|
|
await expect(result).resolves.toBe(false);
|
|
expect(jumpClient.end).toHaveBeenCalledOnce();
|
|
vi.useRealTimers();
|
|
});
|
|
});
|