mirror of
https://github.com/HKUDS/nanobot.git
synced 2026-08-04 16:38:49 +00:00
96 lines
3.1 KiB
TypeScript
96 lines
3.1 KiB
TypeScript
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
|
|
import {
|
|
getRuntimeHost,
|
|
initializeLoopbackRuntimeHost,
|
|
isNativeRuntime,
|
|
} from "@/lib/runtime";
|
|
|
|
afterEach(() => {
|
|
Reflect.deleteProperty(window, "nanobotHost");
|
|
window.sessionStorage.clear();
|
|
window.history.replaceState(null, "", "/");
|
|
initializeLoopbackRuntimeHost();
|
|
vi.unstubAllGlobals();
|
|
});
|
|
|
|
describe("runtime host facade", () => {
|
|
it("defaults to browser runtime without host actions", () => {
|
|
const host = getRuntimeHost();
|
|
|
|
expect(host.surface).toBe("browser");
|
|
expect(host.pickFolder).toBeUndefined();
|
|
expect(isNativeRuntime()).toBe(false);
|
|
});
|
|
|
|
it("wraps native host actions behind the runtime facade", async () => {
|
|
const pickFolder = vi.fn(async () => "/tmp/project");
|
|
const restartEngine = vi.fn(async () => undefined);
|
|
Object.defineProperty(window, "nanobotHost", {
|
|
configurable: true,
|
|
value: {
|
|
getRuntimeInfo: vi.fn(),
|
|
restartEngine,
|
|
pickFolder,
|
|
openLogs: vi.fn(async () => undefined),
|
|
exportDiagnostics: vi.fn(async () => "/tmp/diagnostics.txt"),
|
|
},
|
|
});
|
|
|
|
const host = getRuntimeHost();
|
|
|
|
expect(host.surface).toBe("native");
|
|
expect(isNativeRuntime()).toBe(true);
|
|
await expect(host.pickFolder?.()).resolves.toBe("/tmp/project");
|
|
await host.restartEngine?.();
|
|
expect(pickFolder).toHaveBeenCalledTimes(1);
|
|
expect(restartEngine).toHaveBeenCalledTimes(1);
|
|
});
|
|
|
|
it("treats server-reported native surface as native for UI labels", () => {
|
|
expect(isNativeRuntime("native")).toBe(true);
|
|
});
|
|
|
|
it("installs an authenticated loopback folder picker from the URL fragment", async () => {
|
|
const token = "a".repeat(43);
|
|
const fetchMock = vi.fn(async () => new Response(
|
|
JSON.stringify({ path: "/Users/test/project" }),
|
|
{ status: 200, headers: { "Content-Type": "application/json" } },
|
|
));
|
|
vi.stubGlobal("fetch", fetchMock);
|
|
window.history.replaceState(
|
|
null,
|
|
"",
|
|
`/#/new?bootstrapSecret=secret&nativeHostPort=43123&nativeHostToken=${token}`,
|
|
);
|
|
|
|
expect(initializeLoopbackRuntimeHost()).toBe(true);
|
|
expect(window.location.hash).toBe("#/new?bootstrapSecret=secret");
|
|
expect(isNativeRuntime()).toBe(true);
|
|
await expect(getRuntimeHost().pickFolder?.()).resolves.toBe("/Users/test/project");
|
|
expect(fetchMock).toHaveBeenCalledWith(
|
|
"http://127.0.0.1:43123/v1/pick-folder",
|
|
expect.objectContaining({
|
|
method: "POST",
|
|
headers: { Authorization: `Bearer ${token}` },
|
|
}),
|
|
);
|
|
|
|
window.history.replaceState(null, "", "/#/new");
|
|
expect(initializeLoopbackRuntimeHost()).toBe(true);
|
|
await expect(getRuntimeHost().pickFolder?.()).resolves.toBe("/Users/test/project");
|
|
});
|
|
|
|
it("rejects invalid loopback bridge bootstrap values", () => {
|
|
window.history.replaceState(
|
|
null,
|
|
"",
|
|
"/#/new?nativeHostPort=70000&nativeHostToken=too-short",
|
|
);
|
|
|
|
expect(initializeLoopbackRuntimeHost()).toBe(false);
|
|
expect(window.location.hash).toBe("#/new");
|
|
expect(getRuntimeHost().pickFolder).toBeUndefined();
|
|
});
|
|
});
|