feat(FN-3400): add native shell connection handoff, plugin management CLI/l

This merge adds a complete plugin management system (FN-3565) with CLI commands, a loader, runner, and dashboard routes, along with project-scoped auth storage (FN-3544), native shell connection support for mobile (FN-3400) spanning onboarding, connection manager, and remote desktop handoff, and ref

Fusion-Task-Id: FN-3400
This commit is contained in:
Fusion
2026-05-06 05:24:01 -07:00
committed by gsxdsm
parent fb0e15562d
commit 419c6f3b31
20 changed files with 266 additions and 25 deletions

View File

@@ -31,6 +31,17 @@ describe("connection-profiles", () => {
});
});
it("rejects invalid server URLs", async () => {
const { saveShellProfile } = await import("../plugins/connection-profiles.js");
await expect(saveShellProfile({ name: "Prod", serverUrl: "not-a-url" })).rejects.toThrow(
"Server URL must be a valid absolute URL",
);
await expect(saveShellProfile({ name: "Prod", serverUrl: "ftp://fusion.example.com" })).rejects.toThrow(
"Server URL must use http or https",
);
});
it("clears active profile when deleted", async () => {
const { saveShellProfile, setActiveShellProfile, loadShellProfiles, deleteShellProfile } = await import("../plugins/connection-profiles.js");

View File

@@ -53,6 +53,21 @@ describe("MobileNativeShellBridge", () => {
unsubscribe();
});
it("dispatches shell open manager event", async () => {
const { MobileNativeShellBridge } = await import("../plugins/native-shell.js");
const bridge = new MobileNativeShellBridge(scanner as never);
const listener = vi.fn();
const originalWindow = (globalThis as { window?: Window }).window;
const mockWindow = new EventTarget() as Window;
(globalThis as { window?: Window }).window = mockWindow;
mockWindow.addEventListener("shell:open-connection-manager", listener as EventListener);
await bridge.openConnectionManager();
expect(listener).toHaveBeenCalledTimes(1);
(globalThis as { window?: Window }).window = originalWindow;
});
it("rejects desktop mode switch", async () => {
const { MobileNativeShellBridge } = await import("../plugins/native-shell.js");
const bridge = new MobileNativeShellBridge(scanner as never);

View File

@@ -12,6 +12,11 @@ describe("qr-scanner", () => {
expect(parsed).toEqual({ serverUrl: "https://fusion.example.com", authToken: "abc" });
});
it("parses remote-login rt token payload", () => {
const parsed = parseQrConnectionPayload("https://fusion.example.com/remote-login?rt=abc");
expect(parsed).toEqual({ serverUrl: "https://fusion.example.com", authToken: "abc" });
});
it("uses adapter scanning", async () => {
const scanner = new QrScanner({ scan: vi.fn(async () => "https://fusion.example.com") });
await expect(scanner.scanConnection()).resolves.toEqual({ serverUrl: "https://fusion.example.com", authToken: null });