feat(FN-3407): normalize shell host bootstrap
Introduces a canonical shell host context and normalized bootstrap flow for the dashboard, extracting the host initialization logic into a dedicated `shell-host.ts` module with a `ShellHostContext` provider; updates `App.tsx` and `Header` to use the new context, stabilizes related tests, and documen Fusion-Task-Id: FN-3407
This commit is contained in:
44
packages/dashboard/app/context/ShellHostContext.tsx
Normal file
44
packages/dashboard/app/context/ShellHostContext.tsx
Normal file
@@ -0,0 +1,44 @@
|
||||
import { createContext, useContext, useMemo, type PropsWithChildren } from "react";
|
||||
import { getShellHostContext, type ShellHostContext } from "../shell-host";
|
||||
|
||||
export interface ShellHostContextValue {
|
||||
host: ShellHostContext;
|
||||
isNativeShell: boolean;
|
||||
kind: ShellHostContext["kind"];
|
||||
mode?: "local" | "remote";
|
||||
connectionId?: string;
|
||||
serverUrl?: string;
|
||||
canOpenConnectionManager?: boolean;
|
||||
}
|
||||
|
||||
const DEFAULT_HOST: ShellHostContext = { kind: "browser" };
|
||||
|
||||
const ShellHostContextReact = createContext<ShellHostContextValue>({
|
||||
host: DEFAULT_HOST,
|
||||
isNativeShell: false,
|
||||
kind: "browser",
|
||||
});
|
||||
|
||||
function buildValue(host: ShellHostContext): ShellHostContextValue {
|
||||
const isNativeShell = host.kind !== "browser";
|
||||
return {
|
||||
host,
|
||||
isNativeShell,
|
||||
kind: host.kind,
|
||||
...(isNativeShell ? {
|
||||
mode: host.mode,
|
||||
connectionId: host.connectionId,
|
||||
serverUrl: host.serverUrl,
|
||||
canOpenConnectionManager: host.canOpenConnectionManager,
|
||||
} : {}),
|
||||
};
|
||||
}
|
||||
|
||||
export function ShellHostProvider({ children }: PropsWithChildren) {
|
||||
const value = useMemo(() => buildValue(getShellHostContext()), []);
|
||||
return <ShellHostContextReact.Provider value={value}>{children}</ShellHostContextReact.Provider>;
|
||||
}
|
||||
|
||||
export function useShellHostContext(): ShellHostContextValue {
|
||||
return useContext(ShellHostContextReact);
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
import { render, screen } from "@testing-library/react";
|
||||
import { beforeEach, describe, expect, it } from "vitest";
|
||||
import { ShellHostProvider, useShellHostContext } from "../ShellHostContext";
|
||||
import { __resetShellHostContextForTests } from "../../shell-host";
|
||||
|
||||
function Probe() {
|
||||
const value = useShellHostContext();
|
||||
return <pre data-testid="host">{JSON.stringify(value)}</pre>;
|
||||
}
|
||||
|
||||
describe("ShellHostContext", () => {
|
||||
beforeEach(() => {
|
||||
__resetShellHostContextForTests();
|
||||
window.history.replaceState({}, "", "/");
|
||||
delete (window as Window & Record<string, unknown>).__FUSION_SHELL_HOST_CONTEXT__;
|
||||
});
|
||||
|
||||
it("provides browser defaults", () => {
|
||||
render(
|
||||
<ShellHostProvider>
|
||||
<Probe />
|
||||
</ShellHostProvider>,
|
||||
);
|
||||
|
||||
const value = JSON.parse(screen.getByTestId("host").textContent ?? "{}");
|
||||
expect(value.kind).toBe("browser");
|
||||
expect(value.isNativeShell).toBe(false);
|
||||
});
|
||||
|
||||
it("provides normalized shell fields", () => {
|
||||
(window as Window & Record<string, unknown>).__FUSION_SHELL_HOST_CONTEXT__ = {
|
||||
kind: "desktop-shell",
|
||||
mode: "remote",
|
||||
connectionId: "conn-2",
|
||||
serverUrl: "https://remote.example.com",
|
||||
canOpenConnectionManager: true,
|
||||
};
|
||||
|
||||
render(
|
||||
<ShellHostProvider>
|
||||
<Probe />
|
||||
</ShellHostProvider>,
|
||||
);
|
||||
|
||||
const value = JSON.parse(screen.getByTestId("host").textContent ?? "{}");
|
||||
expect(value.isNativeShell).toBe(true);
|
||||
expect(value.kind).toBe("desktop-shell");
|
||||
expect(value.mode).toBe("remote");
|
||||
expect(value.connectionId).toBe("conn-2");
|
||||
expect(value.serverUrl).toBe("https://remote.example.com");
|
||||
expect(value.canOpenConnectionManager).toBe(true);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user