mirror of
https://github.com/Termix-SSH/Termix.git
synced 2026-10-29 14:45:24 +00:00
feat: move snippets, keybinding actions and macros out of core into plugins
This commit is contained in:
1 parent
d9bba10612
commit
e0c30a4e6f
262 files changed
+9091
-10744
No files matched your search
@@ -42,7 +42,6 @@ function makeHost(overrides: Partial<Host>): Host {
|
||||
ram: null,
|
||||
lastAccess: "",
|
||||
authType: "credential",
|
||||
quickActions: [],
|
||||
enableSsh: true,
|
||||
sshPort: 22,
|
||||
...overrides,
|
||||
|
||||
@@ -428,17 +428,16 @@ describe("connectionOriginAppliesTo", () => {
|
||||
});
|
||||
|
||||
describe("terminal fields", () => {
|
||||
it("sends only the startup snippet in terminalConfig, and the SSH options on their own", () => {
|
||||
it("sends no terminalConfig, and the SSH options on their own", () => {
|
||||
const form = {
|
||||
...createHostEditorForm(null),
|
||||
startupSnippetId: 4,
|
||||
keepaliveInterval: 30,
|
||||
agentForwarding: true,
|
||||
environmentVariables: [{ key: "LANG", value: "C" }],
|
||||
};
|
||||
const payload = buildHostEditorPayload(form, sshOnly);
|
||||
|
||||
expect(payload.terminalConfig).toEqual({ startupSnippetId: 4 });
|
||||
expect(payload).not.toHaveProperty("terminalConfig");
|
||||
expect(payload.sshOptions).toMatchObject({
|
||||
keepaliveInterval: 30,
|
||||
keepaliveCountMax: 5,
|
||||
@@ -457,7 +456,7 @@ describe("terminal fields", () => {
|
||||
|
||||
expect(form.keepaliveInterval).toBe(15);
|
||||
expect(form.allowLegacyAlgorithms).toBe(false);
|
||||
expect(form.startupSnippetId).toBe(2);
|
||||
expect(form).not.toHaveProperty("startupSnippetId");
|
||||
});
|
||||
|
||||
it("leaves the terminal fields out with SSH off", () => {
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import { cleanup, fireEvent, render, screen } from "@testing-library/react";
|
||||
|
||||
const saved = vi.hoisted(() => ({ value: null as string | null }));
|
||||
|
||||
vi.mock("@/api/open-tabs-api", async (importOriginal) => ({
|
||||
...(await importOriginal<Record<string, unknown>>()),
|
||||
getUserPreferences: async () => ({ customKeybindings: saved.value }),
|
||||
}));
|
||||
vi.mock("@/main-axios", () => ({ saveUserPreferences: vi.fn() }));
|
||||
|
||||
const { KeybindingsDialog } = await import("../../sidebar/KeybindingsDialog");
|
||||
const {
|
||||
registerKeybindingAction,
|
||||
registerKeybindingDefault,
|
||||
resetKeybindingRegistry,
|
||||
} = await import("../../shell/keybinding-registry");
|
||||
|
||||
afterEach(() => {
|
||||
cleanup();
|
||||
resetKeybindingRegistry();
|
||||
saved.value = null;
|
||||
});
|
||||
|
||||
const combo = {
|
||||
key: "k",
|
||||
isCode: false,
|
||||
ctrl: true,
|
||||
alt: false,
|
||||
shift: false,
|
||||
meta: false,
|
||||
};
|
||||
|
||||
describe("KeybindingsDialog", () => {
|
||||
it("lists registered defaults and keeps a binding whose plugin is off", async () => {
|
||||
registerKeybindingDefault({
|
||||
id: "default-x",
|
||||
pluginId: "sample",
|
||||
combo,
|
||||
descriptionKey: "sample:builtInX",
|
||||
});
|
||||
saved.value = JSON.stringify([
|
||||
{
|
||||
id: "a",
|
||||
combo,
|
||||
action: { type: "gone.action" },
|
||||
enabled: true,
|
||||
createdAt: "",
|
||||
updatedAt: "",
|
||||
},
|
||||
]);
|
||||
render(<KeybindingsDialog open onOpenChange={() => {}} />);
|
||||
expect(await screen.findByText("sample:builtInX")).toBeTruthy();
|
||||
expect(
|
||||
await screen.findByText("newUi.sidebar.keybindings.unavailableAction"),
|
||||
).toBeTruthy();
|
||||
});
|
||||
|
||||
it("offers every registered action and draws the chosen one's editor", async () => {
|
||||
registerKeybindingAction({
|
||||
id: "sample.send",
|
||||
pluginId: "sample",
|
||||
labelKey: "sample:send",
|
||||
scope: "session",
|
||||
editor: () => <span>sample editor</span>,
|
||||
});
|
||||
render(<KeybindingsDialog open onOpenChange={() => {}} />);
|
||||
fireEvent.click(
|
||||
await screen.findByText("newUi.sidebar.keybindings.addBinding"),
|
||||
);
|
||||
const select = (await screen.findByRole("option", { name: "sample:send" }))
|
||||
.parentElement as HTMLSelectElement;
|
||||
expect([...select.options].map((option) => option.value)).toContain(
|
||||
"nextTab",
|
||||
);
|
||||
fireEvent.change(select, { target: { value: "sample.send" } });
|
||||
expect(await screen.findByText("sample editor")).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -14,7 +14,6 @@ const ALL_GROUPS = new Set<FieldGroup>([
|
||||
"tags",
|
||||
"proxy",
|
||||
"jumpHosts",
|
||||
"quickActions",
|
||||
"featureFlags",
|
||||
"advanced",
|
||||
]);
|
||||
|
||||
@@ -52,13 +52,12 @@ describe("RAIL_ITEMS", () => {
|
||||
// "port-forwarding" to the tunnels plugin's, "serial" to the serial
|
||||
// plugin's, "collab" to the session-sharing plugin's, and "session-logs"
|
||||
// to the session-recording plugin's, "termix-id" to the termix-identity
|
||||
// plugin's, "ssh-tools" to the ssh-terminal plugin's.
|
||||
// plugin's, "ssh-tools" and "macros" to the ssh-terminal plugin's.
|
||||
expect(RAIL_ITEMS.map((item) => item.id)).toEqual([
|
||||
"hosts",
|
||||
"credentials",
|
||||
"connections",
|
||||
"quick-connect",
|
||||
"macros",
|
||||
"sync",
|
||||
]);
|
||||
});
|
||||
@@ -80,7 +79,7 @@ describe("RAIL_ITEMS", () => {
|
||||
[...RAIL_ITEMS, ...RAIL_UTILITY_ITEMS]
|
||||
.filter((item) => item.promotable)
|
||||
.map((item) => item.id),
|
||||
).toEqual(["macros"]);
|
||||
).toEqual([]);
|
||||
});
|
||||
|
||||
it("derives promotableIds from the promotable flag", () => {
|
||||
@@ -117,7 +116,7 @@ describe("RAIL_ITEMS", () => {
|
||||
});
|
||||
|
||||
it("only offers reference panels in the right dock", () => {
|
||||
expect(rightDockableIds()).toEqual(["connections", "macros"]);
|
||||
expect(rightDockableIds()).toEqual(["connections"]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -131,10 +130,10 @@ describe("registered rail items", () => {
|
||||
});
|
||||
|
||||
it("places items after their anchor, keeping their own order", () => {
|
||||
registerRailItem(item("second", { after: "macros", order: 2 }));
|
||||
registerRailItem(item("first", { after: "macros", order: 1 }));
|
||||
registerRailItem(item("second", { after: "connections", order: 2 }));
|
||||
registerRailItem(item("first", { after: "connections", order: 1 }));
|
||||
const ids = visibleRailItems().map((entry) => entry.id);
|
||||
const at = ids.indexOf("macros");
|
||||
const at = ids.indexOf("connections");
|
||||
expect(ids.slice(at + 1, at + 3)).toEqual(["first", "second"]);
|
||||
});
|
||||
|
||||
|
||||
@@ -25,7 +25,6 @@ function host(id: string, name: string): Host {
|
||||
authType: "password",
|
||||
pin: false,
|
||||
enableSsh: true,
|
||||
quickActions: [],
|
||||
} as Host;
|
||||
}
|
||||
|
||||
|
||||
@@ -69,7 +69,6 @@ const baseHost: Host = {
|
||||
enableRdp: true,
|
||||
enableVnc: true,
|
||||
enableTelnet: true,
|
||||
quickActions: [],
|
||||
} as unknown as Host;
|
||||
|
||||
const noop = () => {};
|
||||
|
||||
Reference in new issue
Block a user