feat: move terminal settings, look and ssh tools into ssh-terminal plugin

This commit is contained in:
LukeGus committed 2026-09-29 02:38:37 -05:00
1 parent ffa872ebd3
commit d9bba10612
242 files changed
+25071 -7207

No files matched your search

@@ -0,0 +1,88 @@
import { afterEach, describe, expect, it, vi } from "vitest";
import { cleanup, fireEvent, render, screen } from "@testing-library/react";
import { HostTerminalSettings } from "../../../src/frontend/settings/HostTerminalSettings";
globalThis.ResizeObserver ??= class {
observe() {}
unobserve() {}
disconnect() {}
} as unknown as typeof ResizeObserver;
afterEach(cleanup);
type Form = Record<string, unknown>;
/** The switch on the setting row labelled with this key. */
function switchFor(label: string): HTMLElement {
const row = screen.getByText(label).closest("div.justify-between")!;
return row.querySelector("button")!;
}
function renderSettings(form: Form = { pluginSettings: {} }) {
let current: Form = form;
const setField = vi.fn();
const updateForm = vi.fn((patch: (form: Form) => Form) => {
current = patch(current);
});
render(
<HostTerminalSettings
form={form}
setField={setField}
updateForm={updateForm}
host={{ id: "1", name: "box", ip: "10.0.0.1", port: 22 }}
snippets={[{ id: 7, name: "deploy" }]}
/>,
);
return { setField, updateForm, current: () => current };
}
describe("HostTerminalSettings", () => {
it("renders the appearance and behavior cards", () => {
renderSettings();
expect(screen.getByText("hosts.terminalAppearance")).toBeTruthy();
expect(screen.getByText("hosts.behaviorAndAdvanced")).toBeTruthy();
});
it("leaves the SSH connection options to the core SSH tab", () => {
renderSettings();
expect(screen.queryByText("hosts.keepaliveIntervalLabel")).toBeNull();
expect(screen.queryByText("hosts.environmentVariablesLabel")).toBeNull();
expect(screen.queryByText("hosts.sshAgentForwardingLabel")).toBeNull();
});
it("draws the auto-fill switches that left the SSH tab", () => {
renderSettings();
expect(screen.getByText("hosts.passwordPromptAutoFillLabel")).toBeTruthy();
expect(screen.getByText("hosts.sudoPasswordAutoFillLabel")).toBeTruthy();
});
it("sets the startup snippet, a core host field, from the offered snippets", () => {
const { setField } = renderSettings();
const select = screen
.getByRole("option", { name: "deploy" })
.closest("select")!;
fireEvent.change(select, { target: { value: "7" } });
expect(setField).toHaveBeenCalledWith("startupSnippetId", 7);
});
it("writes its values into the host's ssh-terminal settings", () => {
const { current } = renderSettings({
pluginSettings: { other: { keep: true } },
});
fireEvent.click(switchFor("hosts.enableAutoMosh"));
expect(current().pluginSettings).toEqual({
other: { keep: true },
"ssh-terminal": { autoMosh: true },
});
});
it("takes the host off the user's look when the look changes", () => {
const { current } = renderSettings({
pluginSettings: { "ssh-terminal": { inheritAppearance: false } },
});
fireEvent.click(switchFor("hosts.cursorBlinking"));
expect(
(current().pluginSettings as Record<string, Form>)["ssh-terminal"],
).toMatchObject({ cursorBlink: false, inheritAppearance: false });
});
});
@@ -0,0 +1,37 @@
import { afterEach, describe, expect, it, vi } from "vitest";
import { cleanup, fireEvent, render, screen } from "@testing-library/react";
import { TerminalDefaultsSettings } from "../../../src/frontend/settings/TerminalDefaultsSettings";
afterEach(cleanup);
describe("TerminalDefaultsSettings", () => {
it("counts the defaults the user set", () => {
render(
<TerminalDefaultsSettings
pluginId="ssh-terminal"
values={{ terminalDefaults: { fontSize: 18, cursorBlink: false } }}
setValue={vi.fn()}
running
/>,
);
expect(screen.getByText("2")).toBeTruthy();
});
it("applies the dialog's values to the terminalDefaults setting", () => {
const setValue = vi.fn();
render(
<TerminalDefaultsSettings
pluginId="ssh-terminal"
values={{ terminalDefaults: { fontSize: 18 } }}
setValue={setValue}
running
/>,
);
fireEvent.click(screen.getByText("terminalDefaults.manage"));
fireEvent.change(screen.getByDisplayValue("18"), {
target: { value: "20" },
});
fireEvent.click(screen.getByText("terminalDefaults.apply"));
expect(setValue).toHaveBeenCalledWith("terminalDefaults", { fontSize: 20 });
});
});
@@ -0,0 +1,62 @@
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { moveLocalTerminalPreferences } from "../../../src/frontend/settings/local-preferences-migration";
import { resetTerminalClientSettings } from "../../../src/frontend/terminal-settings";
function api(user: Record<string, unknown>) {
return {
get: vi.fn(async () => ({ data: { user } })),
put: vi.fn(async () => ({ data: {} })),
};
}
beforeEach(() => {
localStorage.clear();
resetTerminalClientSettings();
});
afterEach(() => resetTerminalClientSettings());
describe("moveLocalTerminalPreferences", () => {
it("does nothing when the browser kept nothing", async () => {
const client = api({});
await moveLocalTerminalPreferences({ api: client as never });
expect(client.get).not.toHaveBeenCalled();
});
it("moves the browser's values into settings still at their default, once", async () => {
localStorage.setItem("terminalLocalEchoMode", "on");
localStorage.setItem("terminalLinkClickBehavior", "direct");
localStorage.setItem("commandAutocomplete", "true");
const client = api({ commandAutocomplete: false });
await moveLocalTerminalPreferences({ api: client as never });
expect(client.put).toHaveBeenCalledWith("/user-settings", {
localEcho: "on",
linkClickBehavior: "direct",
commandAutocomplete: true,
});
expect(localStorage.getItem("terminalLocalEchoMode")).toBeNull();
expect(localStorage.getItem("commandAutocomplete")).toBeNull();
});
it("keeps a value the user already changed on the server", async () => {
localStorage.setItem("terminalLocalEchoMode", "off");
const client = api({ localEcho: "on" });
await moveLocalTerminalPreferences({ api: client as never });
expect(client.put).not.toHaveBeenCalled();
expect(localStorage.getItem("terminalLocalEchoMode")).toBeNull();
});
it("keeps the browser values for next time when the server is unreachable", async () => {
localStorage.setItem("terminalLocalEchoMode", "on");
const client = {
get: vi.fn(async () => {
throw new Error("offline");
}),
put: vi.fn(),
};
await moveLocalTerminalPreferences({ api: client as never });
expect(localStorage.getItem("terminalLocalEchoMode")).toBe("on");
});
});
@@ -0,0 +1,17 @@
import { describe, expect, it } from "vitest";
import {
fromTriState,
toTriState,
} from "../../../src/frontend/settings/tri-state";
describe("tri-state", () => {
it("keeps unset booleans distinct from false", () => {
expect(toTriState(undefined)).toBe("inherit");
expect(toTriState(true)).toBe("on");
expect(toTriState(false)).toBe("off");
expect(fromTriState("inherit")).toBeUndefined();
expect(fromTriState("on")).toBe(true);
expect(fromTriState("off")).toBe(false);
});
});