fix(FN-2525): harden remote access auth and tunnel regression coverage
- Add regression tests across CLI, core, dashboard, and engine for remote access auth, settings parity, and serve/TUI callback wiring - Expand dashboard route and modal coverage for remote settings/auth flows including node environment behaviors - Redact provider-switch failure details in tunnel process manager to avoid leaking sensitive provider diagnostics - Update route registration and engine lifecycle tests to lock in remote-access behavior under real execution paths
This commit is contained in:
@@ -360,6 +360,16 @@ const mocks = vi.hoisted(() => {
|
||||
});
|
||||
const notifier = notifierCtor();
|
||||
|
||||
const remoteStatus = {
|
||||
provider: "cloudflare" as const,
|
||||
state: "running" as const,
|
||||
pid: 1234,
|
||||
startedAt: new Date().toISOString(),
|
||||
stoppedAt: null,
|
||||
url: "https://remote.example.com",
|
||||
lastError: null,
|
||||
};
|
||||
|
||||
const engine = {
|
||||
start: vi.fn(async () => {
|
||||
await store.init();
|
||||
@@ -412,6 +422,15 @@ const mocks = vi.hoisted(() => {
|
||||
getMissionAutopilot: () => missionAutopilot,
|
||||
getMissionExecutionLoop: () => missionExecutionLoop,
|
||||
})),
|
||||
getRemoteTunnelManager: vi.fn(() => ({ getStatus: vi.fn(() => remoteStatus) })),
|
||||
getRemoteTunnelRestoreDiagnostics: vi.fn(() => ({
|
||||
outcome: "skipped",
|
||||
reason: "not_attempted",
|
||||
at: new Date().toISOString(),
|
||||
provider: null,
|
||||
})),
|
||||
startRemoteTunnel: vi.fn(async () => remoteStatus),
|
||||
stopRemoteTunnel: vi.fn(async () => ({ ...remoteStatus, state: "stopped" as const, provider: null, pid: null, url: null })),
|
||||
onMerge: vi.fn().mockResolvedValue(undefined),
|
||||
};
|
||||
projectEngineInstances.push(engine);
|
||||
@@ -693,6 +712,22 @@ describe("runServe", () => {
|
||||
await triggerSignal("SIGINT");
|
||||
});
|
||||
|
||||
it("passes remote-capable engine hooks into headless createServer for fn serve parity", async () => {
|
||||
const { createServer } = await import("@fusion/dashboard");
|
||||
|
||||
await runServe(0, {});
|
||||
|
||||
expect(createServer).toHaveBeenCalledTimes(1);
|
||||
const serverOptions = createServer.mock.calls[0][1];
|
||||
expect(serverOptions).toMatchObject({ headless: true });
|
||||
expect(serverOptions.engine).toBeDefined();
|
||||
expect(typeof serverOptions.engine.startRemoteTunnel).toBe("function");
|
||||
expect(typeof serverOptions.engine.stopRemoteTunnel).toBe("function");
|
||||
expect(typeof serverOptions.engine.getRemoteTunnelManager).toBe("function");
|
||||
|
||||
await triggerSignal("SIGINT");
|
||||
});
|
||||
|
||||
it("sets enginePaused when started with paused=true", async () => {
|
||||
await runServe(0, { paused: true });
|
||||
|
||||
|
||||
@@ -471,6 +471,44 @@ describe("Settings view", () => {
|
||||
unmount();
|
||||
});
|
||||
|
||||
it("wires P/U remote actions to persistent token refresh and URL handoff state", async () => {
|
||||
const controller = newController();
|
||||
controller.setSystemInfo(makeSystemInfo());
|
||||
const regeneratePersistentToken = vi.fn(async () => ({
|
||||
maskedToken: "tok_****",
|
||||
tokenType: "persistent" as const,
|
||||
expiresAt: null,
|
||||
}));
|
||||
const getRemoteUrl = vi.fn(async () => ({
|
||||
url: "https://remote.example.com/remote-login?rt=masked",
|
||||
tokenType: "persistent" as const,
|
||||
expiresAt: null,
|
||||
}));
|
||||
|
||||
controller.setInteractiveData(makeInteractiveData({
|
||||
remote: {
|
||||
regeneratePersistentToken,
|
||||
getRemoteUrl,
|
||||
},
|
||||
}));
|
||||
controller.setMode("interactive");
|
||||
controller.setInteractiveView("settings");
|
||||
|
||||
const { lastFrame, stdin, unmount } = render(renderDashboardAppNode(controller));
|
||||
stdin.write("\t");
|
||||
await new Promise((r) => setTimeout(r, 20));
|
||||
|
||||
stdin.write("P");
|
||||
await waitForFrameContains(lastFrame, "Persistent token: tok_****");
|
||||
expect(regeneratePersistentToken).toHaveBeenCalledTimes(1);
|
||||
|
||||
stdin.write("U");
|
||||
await waitForFrameContains(lastFrame, "Auth URL: https://remote.example.com/remote-login?rt=masked");
|
||||
expect(getRemoteUrl).toHaveBeenCalledWith("persistent", undefined);
|
||||
|
||||
unmount();
|
||||
});
|
||||
|
||||
it("keeps global shortcuts inactive during TTL input", async () => {
|
||||
const controller = newController();
|
||||
controller.setSystemInfo(makeSystemInfo());
|
||||
|
||||
Reference in New Issue
Block a user