fix: finish 2.9.0 plugin moves and get every check green

This commit is contained in:
LukeGus committed 2026-09-24 23:35:18 -05:00
1 parent 8c1e02af89
commit 6489b62ece
335 files changed
+29878 -17749

No files matched your search

@@ -42,15 +42,6 @@ function makeHost(overrides: Partial<Host>): Host {
ram: null,
lastAccess: "",
authType: "credential",
enableTerminal: true,
enableTerminalToolbar: true,
enableCommandHistory: true,
enableTunnel: false,
serverTunnels: [],
enableFileManager: true,
enableProxmox: false,
enableProxmoxStats: false,
enableTmuxMonitor: false,
quickActions: [],
enableSsh: true,
sshPort: 22,
+6 -123
View File
@@ -334,135 +334,18 @@ describe("sudo password persistence indicator", () => {
});
});
describe("Proxmox / Proxmox Stats independent toggles", () => {
it("defaults enableProxmoxStats to false with sane pollInterval/nodeName defaults", () => {
const form = createHostEditorForm(null);
expect(form.enableProxmoxStats).toBe(false);
expect(form.proxmoxStatsConfig).toEqual({
pollInterval: 60,
nodeName: null,
});
expect(form.enableProxmox).toBe(false);
});
it("seeds both configs independently from an existing host", () => {
describe("plugin host settings", () => {
it("keeps them on the form and out of the host payload", () => {
const host = {
pluginSettings: {
proxmox: {
enableProxmox: true,
proxmoxConfig: { windowsPatterns: "win", dockerPatterns: "docker" },
enableProxmoxStats: true,
proxmoxStatsConfig: { pollInterval: 30, nodeName: "pve-custom" },
},
},
pluginSettings: { proxmox: { enableProxmox: true } },
} as unknown as Host;
const form = createHostEditorForm(host);
expect(form.enableProxmox).toBe(true);
expect(form.enableProxmoxStats).toBe(true);
expect(form.proxmoxStatsConfig).toEqual({
pollInterval: 30,
nodeName: "pve-custom",
});
});
it("nulls proxmoxStatsConfig in the payload when enableProxmoxStats is off, regardless of enableProxmox", () => {
const form = {
...createHostEditorForm(null),
enableProxmox: true,
proxmoxConfig: {
defaultCredentialId: null,
defaultAuthType: "password",
windowsPatterns: "win",
dockerPatterns: "docker",
preferredPrefixes: "",
},
enableProxmoxStats: false,
proxmoxStatsConfig: { pollInterval: 45, nodeName: "leftover" },
};
const payload = buildHostEditorPayload(form, sshOnly);
expect(payload.enableProxmox).toBe(true);
expect(payload.proxmoxConfig).not.toBeNull();
expect(payload.enableProxmoxStats).toBe(false);
expect(payload.proxmoxStatsConfig).toBeNull();
});
it("keeps proxmoxConfig null in the payload when enableProxmox is off, even though enableProxmoxStats is on", () => {
const form = {
...createHostEditorForm(null),
enableProxmox: false,
enableProxmoxStats: true,
proxmoxStatsConfig: { pollInterval: 90, nodeName: "pve1" },
};
const payload = buildHostEditorPayload(form, sshOnly);
expect(payload.enableProxmox).toBe(false);
expect(payload.proxmoxConfig).toBeNull();
expect(payload.enableProxmoxStats).toBe(true);
expect(payload.proxmoxStatsConfig).toEqual({
pollInterval: 90,
nodeName: "pve1",
});
});
it("preserves the source identity when editing an imported Proxmox guest", () => {
const source = {
source: "proxmox" as const,
sourceHostId: 7,
node: "pve1",
vmid: 101,
type: "qemu" as const,
lastSeenAt: "2026-08-14T00:00:00.000Z",
lastStatus: "running",
missingSince: null,
};
const form = {
...createHostEditorForm({
pluginSettings: {
proxmox: {
enableProxmox: false,
proxmoxConfig: { source },
},
},
} as unknown as Host),
name: "Edited guest",
};
const payload = buildHostEditorPayload(form, sshOnly);
expect(payload.enableProxmox).toBe(false);
expect(payload.proxmoxConfig).toEqual({ source });
});
it("sends both configs when both toggles are on", () => {
const form = {
...createHostEditorForm(null),
enableProxmox: true,
proxmoxConfig: {
defaultCredentialId: null,
defaultAuthType: "password",
windowsPatterns: "win",
dockerPatterns: "docker",
preferredPrefixes: "",
},
enableProxmoxStats: true,
proxmoxStatsConfig: { pollInterval: 60, nodeName: null },
};
const payload = buildHostEditorPayload(form, sshOnly);
expect(payload.enableProxmox).toBe(true);
expect(payload.proxmoxConfig).not.toBeNull();
expect(payload.enableProxmoxStats).toBe(true);
expect(payload.proxmoxStatsConfig).toEqual({
pollInterval: 60,
nodeName: null,
});
expect(form.pluginSettings).toEqual({ proxmox: { enableProxmox: true } });
expect(payload).not.toHaveProperty("enableProxmox");
expect(payload).not.toHaveProperty("pluginSettings");
});
});
+12 -18
View File
@@ -45,20 +45,6 @@ function sshHost(
pin: false,
authType: "password",
connectionType: "ssh",
enableTerminal: true,
enableSessionLogging: false,
enableCommandHistory: false,
enableTunnel: false,
enableFileManager: false,
enableTmuxMonitor: false,
enableTerminalToolbar: true,
showTerminalInSidebar: true,
showFileManagerInSidebar: false,
showTunnelInSidebar: false,
showDockerInSidebar: false,
showServerStatsInSidebar: false,
defaultPath: "",
tunnelConnections: [],
createdAt: "2026-01-01T00:00:00.000Z",
updatedAt: "2026-01-01T00:00:00.000Z",
status: "online",
@@ -76,9 +62,13 @@ function rawPayload() {
port: 22,
username: "deploy",
password: "hunter2",
guacamoleConfig: {
"gateway-hostname": "gw.example.com",
"gateway-password": "gw-secret",
pluginSettings: {
"remote-desktop": {
guacamoleConfig: {
"gateway-hostname": "gw.example.com",
"gateway-password": "gw-secret",
},
},
},
},
],
@@ -207,6 +197,10 @@ describe("HostExportDialog - credential handling", () => {
expect(text).toContain("gw.example.com");
const parsed = JSON.parse(text);
expect(parsed.hosts[0].guacamoleConfig["gateway-password"]).toBeNull();
expect(
parsed.hosts[0].pluginSettings["remote-desktop"].guacamoleConfig[
"gateway-password"
],
).toBeNull();
});
});
@@ -62,6 +62,14 @@ function shareRaw(): ExportPayload {
};
}
function gatewayConfig(host: Record<string, unknown>): Record<string, unknown> {
const plugins = host.pluginSettings as Record<
string,
Record<string, unknown>
>;
return plugins["remote-desktop"].guacamoleConfig as Record<string, unknown>;
}
function rdpRaw(): ExportPayload {
return {
hosts: [
@@ -72,9 +80,13 @@ function rdpRaw(): ExportPayload {
port: 3389,
username: "admin",
password: null,
guacamoleConfig: {
"gateway-hostname": "gw.example.com",
"gateway-password": "gw-secret",
pluginSettings: {
"remote-desktop": {
guacamoleConfig: {
"gateway-hostname": "gw.example.com",
"gateway-password": "gw-secret",
},
},
},
},
],
@@ -198,21 +210,21 @@ describe("buildExportPayload", () => {
it("nulls the guacamole gateway password when credentials are excluded", () => {
const out = buildExportPayload(rdpRaw(), null, ALL_GROUPS, false);
const config = out.hosts[0].guacamoleConfig as Record<string, unknown>;
const config = gatewayConfig(out.hosts[0]);
expect(config["gateway-password"]).toBeNull();
expect(config["gateway-hostname"]).toBe("gw.example.com");
});
it("keeps the guacamole gateway password when credentials are included", () => {
const out = buildExportPayload(rdpRaw(), null, ALL_GROUPS, true);
const config = out.hosts[0].guacamoleConfig as Record<string, unknown>;
const config = gatewayConfig(out.hosts[0]);
expect(config["gateway-password"]).toBe("gw-secret");
});
it("does not mutate the source payload when nulling nested secrets", () => {
const raw = rdpRaw();
buildExportPayload(raw, null, ALL_GROUPS, false);
const config = raw.hosts[0].guacamoleConfig as Record<string, unknown>;
const config = gatewayConfig(raw.hosts[0]);
expect(config["gateway-password"]).toBe("gw-secret");
});
@@ -260,7 +272,7 @@ describe("maskSecrets", () => {
it("masks the guacamole gateway password", () => {
const out = maskSecrets(rdpRaw());
const config = out.hosts[0].guacamoleConfig as Record<string, unknown>;
const config = gatewayConfig(out.hosts[0]);
expect(config["gateway-password"]).toBe("<included>");
expect(config["gateway-hostname"]).toBe("gw.example.com");
expect(JSON.stringify(out)).not.toContain("gw-secret");
@@ -25,9 +25,6 @@ function host(id: string, name: string): Host {
authType: "password",
pin: false,
enableSsh: true,
enableTerminal: true,
enableTunnel: false,
enableFileManager: true,
quickActions: [],
} as Host;
}