fix(FN-4939): stabilize desktop test mocks and restore lint/type safety

Fusion-Task-Id: FN-4939
Fusion-Task-Lineage: b2a00edb-5245-4223-97e4-0a16dd2c3289
This commit is contained in:
Fusion (runfusion.ai)
2026-05-17 11:47:49 -07:00
committed by gsxdsm
parent 2619a170e2
commit 329b102eb2
4 changed files with 39 additions and 11 deletions

View File

@@ -2,7 +2,6 @@ import { SecretsStoreError, type SecretScope } from "@fusion/core";
import { ApiError, badRequest } from "../api-error.js";
import type { ApiRouteRegistrar } from "./types.js";
const VALID_SCOPES: SecretScope[] = ["project", "global"];
const VALID_POLICIES = ["auto", "prompt", "deny"] as const;
function parseScope(scope: unknown): SecretScope {
@@ -52,27 +51,29 @@ export const registerSecretsRoutes: ApiRouteRegistrar = (ctx) => {
try {
assertObject(req.body);
const { scope, key, value, description, accessPolicy, envExportable, envExportKey } = req.body;
if (!VALID_SCOPES.includes(scope as SecretScope)) {
throw badRequest("scope must be 'project' or 'global'");
}
const parsedScope = parseScope(scope);
if (typeof key !== "string" || key.trim().length === 0) {
throw badRequest("key must be a non-empty string");
}
if (typeof value !== "string") {
throw badRequest("value must be a string");
}
if (accessPolicy !== undefined && !VALID_POLICIES.includes(accessPolicy as (typeof VALID_POLICIES)[number])) {
throw badRequest("accessPolicy must be one of: auto, prompt, deny");
let parsedAccessPolicy: (typeof VALID_POLICIES)[number] | undefined;
if (accessPolicy !== undefined) {
if (!VALID_POLICIES.includes(accessPolicy as (typeof VALID_POLICIES)[number])) {
throw badRequest("accessPolicy must be one of: auto, prompt, deny");
}
parsedAccessPolicy = accessPolicy as (typeof VALID_POLICIES)[number];
}
const { store: scopedStore } = await getProjectContext(req);
const secretsStore = await scopedStore.getSecretsStore();
const secret = await secretsStore.createSecret({
scope,
key,
plaintextValue: value,
scope: parsedScope,
key: key as string,
plaintextValue: value as string,
description: typeof description === "string" ? description : null,
accessPolicy,
accessPolicy: parsedAccessPolicy,
envExportable: envExportable === undefined ? undefined : Boolean(envExportable),
envExportKey: typeof envExportKey === "string" ? envExportKey : null,
});

View File

@@ -18,8 +18,12 @@ const mocks = vi.hoisted(() => {
on: vi.fn((event: string, handler: (...args: unknown[]) => void) => {
listeners.set(event, handler);
}),
once: vi.fn((event: string, handler: (...args: unknown[]) => void) => {
listeners.set(event, handler);
}),
hide: vi.fn(),
show: vi.fn(),
focus: vi.fn(),
maximize: vi.fn(),
isDestroyed: vi.fn(() => false),
getBounds: vi.fn(() => ({ x: 50, y: 80, width: 1280, height: 900 })),
@@ -64,6 +68,10 @@ const mocks = vi.hoisted(() => {
createEmpty: vi.fn(() => ({ id: "empty" })),
};
const screen = {
getAllDisplays: vi.fn(() => [{ workArea: { x: 0, y: 0, width: 1920, height: 1080 } }]),
};
const buildAppMenu = vi.fn(() => {
callLog.push("buildAppMenu");
});
@@ -120,6 +128,7 @@ const mocks = vi.hoisted(() => {
BrowserWindow,
Tray,
nativeImage,
screen,
buildAppMenu,
setupTray,
registerIpcHandlers,
@@ -142,6 +151,7 @@ vi.mock("electron", () => ({
BrowserWindow: mocks.BrowserWindow,
Tray: mocks.Tray,
nativeImage: mocks.nativeImage,
screen: mocks.screen,
}));
vi.mock("../menu.js", () => ({
@@ -173,6 +183,7 @@ vi.mock("../native.js", () => ({
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}`),
clampWindowStateToVisibleDisplay: vi.fn((state) => state),
}));
vi.mock("../local-runtime.js", () => ({

View File

@@ -13,12 +13,15 @@ const mocks = vi.hoisted(() => {
const browserWindow = {
on: vi.fn(),
once: vi.fn(),
loadURL: vi.fn(),
loadFile: vi.fn(),
isDestroyed: vi.fn(() => false),
getBounds: vi.fn(() => ({ x: 0, y: 0, width: 800, height: 600 })),
isMaximized: vi.fn(() => false),
hide: vi.fn(),
show: vi.fn(),
focus: vi.fn(),
maximize: vi.fn(),
webContents: { send: vi.fn() },
};
@@ -33,7 +36,11 @@ const mocks = vi.hoisted(() => {
getServerPort: vi.fn(() => undefined),
};
return { app, appHandlers, BrowserWindow, Tray, browserWindow, localRuntimeManager };
const screen = {
getAllDisplays: vi.fn(() => [{ workArea: { x: 0, y: 0, width: 1920, height: 1080 } }]),
};
return { app, appHandlers, BrowserWindow, Tray, browserWindow, localRuntimeManager, screen };
});
vi.mock("electron", () => ({
@@ -41,6 +48,7 @@ vi.mock("electron", () => ({
BrowserWindow: mocks.BrowserWindow,
Tray: mocks.Tray,
nativeImage: { createEmpty: vi.fn(() => ({})) },
screen: mocks.screen,
}));
vi.mock("../renderer.js", () => ({ isUrlRenderer: vi.fn(() => true), getRendererUrl: vi.fn(() => "http://localhost"), getRendererFilePath: vi.fn(() => "index.html") }));
@@ -54,6 +62,7 @@ vi.mock("../native.js", () => ({
saveDesktopLaunchMode: vi.fn(async () => undefined),
saveWindowState: vi.fn(),
setupAutoUpdater: vi.fn(),
clampWindowStateToVisibleDisplay: vi.fn((state) => state),
}));
vi.mock("../deep-link.js", () => ({ registerDeepLinkProtocol: vi.fn(), setupDeepLinkHandler: vi.fn() }));
vi.mock("../local-runtime.js", () => ({ LocalRuntimeManager: vi.fn(() => mocks.localRuntimeManager) }));

View File

@@ -11,8 +11,10 @@ const mocks = vi.hoisted(() => {
loadURL: vi.fn(),
loadFile: vi.fn(),
on: vi.fn(),
once: vi.fn(),
hide: vi.fn(),
show: vi.fn(),
focus: vi.fn(),
maximize: vi.fn(),
};
@@ -29,6 +31,9 @@ const mocks = vi.hoisted(() => {
nativeImage: {
createEmpty: vi.fn(() => ({ id: "empty-image" })),
},
screen: {
getAllDisplays: vi.fn(() => [{ workArea: { x: 0, y: 0, width: 1920, height: 1080 } }]),
},
browserWindow,
buildAppMenu: vi.fn(),
setupTray: vi.fn(),
@@ -48,6 +53,7 @@ vi.mock("electron", () => ({
BrowserWindow: mocks.BrowserWindow,
Tray: mocks.Tray,
nativeImage: mocks.nativeImage,
screen: mocks.screen,
}));
vi.mock("../menu.js", () => ({
@@ -78,6 +84,7 @@ vi.mock("../native.js", () => ({
saveDesktopLaunchMode: mocks.saveDesktopLaunchMode,
saveWindowState: mocks.saveWindowState,
setupAutoUpdater: mocks.setupAutoUpdater,
clampWindowStateToVisibleDisplay: vi.fn((state) => state),
}));
// Mock renderer module