feat(FN-3406): add shell context hook plumbing for dashboard
Adds a new `useShellContext` hook with tests to the dashboard, integrated into `App.tsx` and `Header.tsx` to provide shell context plumbing throughout the UI. Fusion-Task-Id: FN-3406
This commit is contained in:
@@ -128,6 +128,7 @@ describe("ipc handlers", () => {
|
||||
expect(channels.has("desktopRuntime:startLocal")).toBe(true);
|
||||
expect(channels.has("desktopRuntime:stopLocal")).toBe(true);
|
||||
expect(channels.has("desktopLaunchMode:getMode")).toBe(true);
|
||||
expect(channels.has("desktopLaunchMode:getContext")).toBe(true);
|
||||
expect(channels.has("desktopLaunchMode:setMode")).toBe(true);
|
||||
expect(channels.has("platform:get")).toBe(true);
|
||||
});
|
||||
@@ -155,12 +156,14 @@ describe("ipc handlers", () => {
|
||||
expect(window.webContents.send).toHaveBeenCalledWith("shell:state", expect.any(Object));
|
||||
});
|
||||
|
||||
it("desktop launch mode handlers return mode and validate payload", async () => {
|
||||
it("desktop launch mode handlers return mode/context and validate payload", async () => {
|
||||
const getDesktopLaunchContext = vi.fn(() => ({ mode: "remote", profileId: "profile_1", serverBaseUrl: "https://remote.example.com" }));
|
||||
const onDesktopLaunchModeChange = vi.fn(async () => undefined);
|
||||
const getDesktopLaunchMode = vi.fn(() => "remote");
|
||||
await registerHandlers({ onDesktopLaunchModeChange, getDesktopLaunchMode });
|
||||
await registerHandlers({ onDesktopLaunchModeChange, getDesktopLaunchMode, getDesktopLaunchContext });
|
||||
|
||||
await expect(mocks.ipcHandlers.get("desktopLaunchMode:getMode")?.({})).resolves.toBe("remote");
|
||||
await expect(mocks.ipcHandlers.get("desktopLaunchMode:getContext")?.({})).resolves.toEqual({ mode: "remote", profileId: "profile_1", serverBaseUrl: "https://remote.example.com" });
|
||||
await expect(mocks.ipcHandlers.get("desktopLaunchMode:setMode")?.({}, "local")).resolves.toBe("remote");
|
||||
await expect(mocks.ipcHandlers.get("desktopLaunchMode:setMode")?.({}, "bad")).rejects.toThrow("Invalid desktop launch mode");
|
||||
expect(onDesktopLaunchModeChange).toHaveBeenCalledWith("local");
|
||||
|
||||
@@ -168,6 +168,11 @@ vi.mock("../native.js", () => ({
|
||||
saveWindowState: mocks.saveWindowState,
|
||||
setupAutoUpdater: mocks.setupAutoUpdater,
|
||||
DEFAULT_WINDOW_STATE: mocks.DEFAULT_WINDOW_STATE,
|
||||
normalizeDesktopRemoteLaunch: vi.fn((settings) => {
|
||||
const active = settings.profiles.find((profile: { id: string }) => profile.id === settings.activeProfileId);
|
||||
return active ? { mode: "remote", profileId: active.id, serverBaseUrl: active.serverUrl.replace(/\/$/, ""), serverLabel: active.name, authToken: active.authToken ?? undefined } : null;
|
||||
}),
|
||||
buildRemoteShellHandoffUrl: vi.fn((launch) => `https://remote.example.com?shellMode=remote&profileId=${launch.profileId}`),
|
||||
}));
|
||||
|
||||
vi.mock("../local-runtime.js", () => ({
|
||||
@@ -180,6 +185,14 @@ vi.mock("../local-runtime.js", () => ({
|
||||
}));
|
||||
|
||||
// Mock renderer module
|
||||
vi.mock("../shell-settings.js", () => ({
|
||||
readShellSettings: vi.fn(async () => ({
|
||||
desktopMode: "remote",
|
||||
activeProfileId: "profile_1",
|
||||
profiles: [{ id: "profile_1", name: "Remote", serverUrl: "https://remote.example.com", authToken: "token" }],
|
||||
})),
|
||||
}));
|
||||
|
||||
vi.mock("../renderer.js", () => ({
|
||||
isDevelopmentMode: vi.fn(() => false),
|
||||
getRendererUrl: vi.fn(() => "file:///path/to/dist/client/index.html"),
|
||||
@@ -375,6 +388,17 @@ describe("main integration", () => {
|
||||
}
|
||||
});
|
||||
|
||||
it("loads remote handoff URL when remembered mode is remote", async () => {
|
||||
mocks.loadDesktopLaunchMode.mockResolvedValueOnce("remote");
|
||||
const { initializeApp } = await importMainModule();
|
||||
|
||||
await initializeApp();
|
||||
|
||||
const [{ instance }] = mocks.windowInstances;
|
||||
expect(instance.loadURL).toHaveBeenCalledWith(expect.stringContaining("shellMode=remote"));
|
||||
expect(mocks.startLocal).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("starts local runtime when remembered mode is local", async () => {
|
||||
mocks.loadDesktopLaunchMode.mockResolvedValueOnce("local");
|
||||
const { initializeApp } = await importMainModule();
|
||||
|
||||
@@ -137,11 +137,24 @@ vi.mock("../native.js", () => ({
|
||||
saveDesktopLaunchMode: mainDeps.saveDesktopLaunchMode,
|
||||
saveWindowState: mainDeps.saveWindowState,
|
||||
setupAutoUpdater: mainDeps.setupAutoUpdater,
|
||||
normalizeDesktopRemoteLaunch: vi.fn((settings) => {
|
||||
const active = settings.profiles.find((profile: { id: string }) => profile.id === settings.activeProfileId);
|
||||
return active ? { mode: "remote", profileId: active.id, serverBaseUrl: active.serverUrl.replace(/\/$/, ""), serverLabel: active.name, authToken: active.authToken ?? undefined } : null;
|
||||
}),
|
||||
buildRemoteShellHandoffUrl: vi.fn((launch) => `https://remote.example.com?shellKind=desktop&shellMode=remote&profileId=${launch.profileId}`),
|
||||
}));
|
||||
vi.mock("../local-runtime.js", () => ({
|
||||
LocalRuntimeManager: mainDeps.LocalRuntimeManager,
|
||||
}));
|
||||
|
||||
vi.mock("../shell-settings.js", () => ({
|
||||
readShellSettings: vi.fn(async () => ({
|
||||
desktopMode: "remote",
|
||||
activeProfileId: "profile_1",
|
||||
profiles: [{ id: "profile_1", name: "Remote", serverUrl: "https://remote.example.com", authToken: "token" }],
|
||||
})),
|
||||
}));
|
||||
|
||||
async function importMainModule() {
|
||||
return import("../main.ts");
|
||||
}
|
||||
@@ -264,13 +277,16 @@ describe("main process", () => {
|
||||
expect(mainDeps.startLocal).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("initializeApp does not start local runtime for remembered remote mode", async () => {
|
||||
it("initializeApp routes remembered remote mode to remote dashboard handoff URL", async () => {
|
||||
mainDeps.loadDesktopLaunchMode.mockResolvedValueOnce("remote");
|
||||
const { initializeApp, getCurrentDesktopLaunchMode } = await importMainModule();
|
||||
|
||||
await initializeApp();
|
||||
|
||||
expect(mainDeps.startLocal).not.toHaveBeenCalled();
|
||||
expect(mocks.browserWindowInstance.loadURL).toHaveBeenCalledWith(
|
||||
expect.stringContaining("shellMode=remote"),
|
||||
);
|
||||
expect(getCurrentDesktopLaunchMode()).toBe("remote");
|
||||
});
|
||||
|
||||
|
||||
@@ -54,13 +54,16 @@ describe("preload", () => {
|
||||
await importPreloadModule();
|
||||
const api = getExposed<{
|
||||
getDesktopLaunchMode: () => Promise<string>;
|
||||
getDesktopLaunchContext: () => Promise<unknown>;
|
||||
setDesktopLaunchMode: (mode: "choose" | "local" | "remote") => Promise<string>;
|
||||
}>("electronAPI");
|
||||
|
||||
await api?.getDesktopLaunchMode();
|
||||
await api?.getDesktopLaunchContext();
|
||||
await api?.setDesktopLaunchMode("local");
|
||||
|
||||
expect(mocks.ipcRenderer.invoke).toHaveBeenCalledWith("desktopLaunchMode:getMode");
|
||||
expect(mocks.ipcRenderer.invoke).toHaveBeenCalledWith("desktopLaunchMode:getContext");
|
||||
expect(mocks.ipcRenderer.invoke).toHaveBeenCalledWith("desktopLaunchMode:setMode", "local");
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user