From 35596d16a5cd862d24c61dfe5d108af937d1f192 Mon Sep 17 00:00:00 2001 From: Neil <4138956+nwparker@users.noreply.github.com> Date: Wed, 21 Oct 2026 21:52:08 -0700 Subject: [PATCH] chore: replace electron-toolkit utilities with Electron APIs (#31824) * chore: replace electron-toolkit utilities with Electron APIs * refactor: reuse development flag within startup preflight --- config/packaged-runtime-node-modules.cjs | 1 - package.json | 1 - pnpm-lock.yaml | 16 ------- src/main/app-icon.test.ts | 27 ++++-------- src/main/app-icon.ts | 5 +-- src/main/ipc/app.test.ts | 4 -- src/main/ipc/app.ts | 3 +- .../agent-status-producer-census.test.ts | 6 --- ...rowser-process-user-agent-ordering.test.ts | 1 - .../startup/codex-hook-startup-wiring.test.ts | 1 - ...pu-lifecycle-install-dir-acl-guard.test.ts | 9 +--- src/main/startup/main-process-preflight.ts | 14 +++--- ...process-ready-duplicate-pty-repair.test.ts | 1 - .../startup/main-process-ready-foundation.ts | 9 ++-- .../main-process-ready-identity-write.test.ts | 44 ++++++++++++++++--- .../startup/main-process-ready-runtime.ts | 3 +- ...-process-runtime-launch-activation.test.ts | 1 - .../startup/main-process-runtime-launch.ts | 3 +- ...ter-linux-package-recovery-actions.test.ts | 1 - .../updater-sqlite-profile-downgrade.test.ts | 1 - src/main/updater-test-harness.ts | 6 --- .../updater.build-channel-selection.test.ts | 1 - src/main/updater.check-failure.test.ts | 10 ++--- src/main/updater.check-preflight.test.ts | 1 - src/main/updater.check-settlement.test.ts | 1 - .../updater.feed-attempt-lifetime.test.ts | 1 - .../updater.headless-serve-install.test.ts | 1 - .../updater.install-failure-cause.test.ts | 6 +-- .../updater.linux-externally-managed.test.ts | 1 - ...updater.linux-root-package-install.test.ts | 1 - src/main/updater.mac-install.test.ts | 9 +--- src/main/updater.nudge-campaign.test.ts | 1 - src/main/updater.prerelease-fallback.test.ts | 1 - .../updater.publishing-window-feed.test.ts | 1 - src/main/updater.quit-and-install.test.ts | 1 - src/main/updater.startup-scheduling.test.ts | 4 +- src/main/updater/updater-build-selection.ts | 3 +- src/main/updater/updater-menu-checks.ts | 3 +- src/main/updater/updater-nudge.ts | 3 +- src/main/updater/updater-remote-status.ts | 3 +- src/main/updater/updater-scheduling.ts | 3 +- src/main/updater/updater-setup.ts | 6 +-- ...reateMainWindow-close-confirmation.test.ts | 3 -- ...MainWindow-low-commit-oom-recovery.test.ts | 3 -- ...teMainWindow-markdown-editor-focus.test.ts | 3 -- ...ainWindow-recovery-reload-watchdog.test.ts | 7 +-- ...MainWindow-renderer-crash-recovery.test.ts | 3 -- ...MainWindow-renderer-launch-failure.test.ts | 3 -- .../createMainWindow-startup-reveal.test.ts | 3 -- ...eateMainWindow-system-resume-relay.test.ts | 3 -- ...ainWindow-terminal-focus-shortcuts.test.ts | 7 +-- .../window/createMainWindow-test-harness.ts | 18 ++++---- ...eateMainWindow-tray-minimize-close.test.ts | 3 -- .../createMainWindow-user-quit-close.test.ts | 3 -- ...ndow-zoom-and-tab-switch-shortcuts.test.ts | 3 -- src/main/window/createMainWindow.test.ts | 3 -- src/main/window/createMainWindow.ts | 5 +-- .../window/dashboard-popout-window.test.ts | 17 ++++--- src/main/window/dashboard-popout-window.ts | 3 +- .../window/main-window-shortcut-routing.ts | 4 +- .../renderer-recovery-reload-watchdog.test.ts | 2 +- .../renderer-recovery-reload-watchdog.ts | 4 +- src/main/window/workspace-space-window.ts | 5 +-- 63 files changed, 112 insertions(+), 211 deletions(-) diff --git a/config/packaged-runtime-node-modules.cjs b/config/packaged-runtime-node-modules.cjs index 62ed2ff47f5..5852e2418b7 100644 --- a/config/packaged-runtime-node-modules.cjs +++ b/config/packaged-runtime-node-modules.cjs @@ -21,7 +21,6 @@ const requireFromProject = createRequire(join(projectDir, 'package.json')) const PACKAGED_RUNTIME_PACKAGE_ROOTS = [ '@anthropic-ai/claude-agent-sdk', - '@electron-toolkit/utils', '@linear/sdk', '@orca/process-host', '@parcel/watcher', diff --git a/package.json b/package.json index d3908c04708..bcaa94766fe 100644 --- a/package.json +++ b/package.json @@ -196,7 +196,6 @@ }, "dependencies": { "@anthropic-ai/claude-agent-sdk": "0.3.284", - "@electron-toolkit/utils": "^4.0.0", "@floating-ui/dom": "1.8.0", "@linear/sdk": "^97.0.0", "@orca/process-host": "workspace:*", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index cdec646005b..0511935d489 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -195,9 +195,6 @@ importers: '@anthropic-ai/claude-agent-sdk': specifier: 0.3.284 version: 0.3.284(@anthropic-ai/sdk@0.122.0(zod@4.6.7))(@modelcontextprotocol/sdk@1.32.1(supports-color@7.2.0)(zod@4.6.7))(zod@4.6.7) - '@electron-toolkit/utils': - specifier: ^4.0.0 - version: 4.0.0(electron@43.7.8(supports-color@7.2.0)) '@floating-ui/dom': specifier: 1.8.0 version: 1.8.0 @@ -889,15 +886,6 @@ packages: peerDependencies: '@types/node': '*' - '@electron-toolkit/utils@4.0.0': - resolution: {integrity: sha512-qXSntwEzluSzKl4z5yFNBknmPGjPa3zFhE4mp9+h0cgokY5ornAeP+CJQDBhKsL1S58aOQfcwkD3NwLZCl+64g==} - peerDependencies: - '@types/electron': '*' - electron: '>=13.0.0' - peerDependenciesMeta: - '@types/electron': - optional: true - '@electron/asar@3.4.1': resolution: {integrity: sha512-i4/rNPRS84t0vSRa2HorerGRXWyF4vThfHesw0dmcWHp+cspK743UanA0suA5Q5y8kzY2y6YKrvbIUn69BCAiA==} engines: {node: '>=10.12.0'} @@ -8265,10 +8253,6 @@ snapshots: dependencies: '@types/node': 24.19.2 - '@electron-toolkit/utils@4.0.0(electron@43.7.8(supports-color@7.2.0))': - dependencies: - electron: 43.7.8(supports-color@7.2.0) - '@electron/asar@3.4.1': dependencies: commander: 5.1.0 diff --git a/src/main/app-icon.test.ts b/src/main/app-icon.test.ts index 520fcbeb150..a082efd8c33 100644 --- a/src/main/app-icon.test.ts +++ b/src/main/app-icon.test.ts @@ -1,30 +1,20 @@ import { EventEmitter } from 'node:events' import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' -const { - browserWindowGetAllWindowsMock, - createFromPathMock, - dockSetIconMock, - isMock, - windowSetIconMock -} = vi.hoisted(() => ({ - browserWindowGetAllWindowsMock: vi.fn(), - createFromPathMock: vi.fn(), - dockSetIconMock: vi.fn(), - isMock: { dev: false }, - windowSetIconMock: vi.fn() -})) +const { browserWindowGetAllWindowsMock, createFromPathMock, dockSetIconMock, windowSetIconMock } = + vi.hoisted(() => ({ + browserWindowGetAllWindowsMock: vi.fn(), + createFromPathMock: vi.fn(), + dockSetIconMock: vi.fn(), + windowSetIconMock: vi.fn() + })) vi.mock('electron', () => ({ - app: { dock: { setIcon: dockSetIconMock } }, + app: { getPath: () => '/test/electron', isPackaged: true, dock: { setIcon: dockSetIconMock } }, BrowserWindow: { getAllWindows: browserWindowGetAllWindowsMock }, nativeImage: { createFromPath: createFromPathMock } })) -vi.mock('@electron-toolkit/utils', () => ({ - is: isMock -})) - vi.mock('../../resources/icon.png?asset', () => ({ default: 'classic-icon' })) @@ -75,7 +65,6 @@ describe('app icon selection', () => { createFromPathMock.mockReset() dockSetIconMock.mockReset() windowSetIconMock.mockReset() - isMock.dev = false }) afterEach(() => { diff --git a/src/main/app-icon.ts b/src/main/app-icon.ts index 8964b9eeb50..5df66bf6885 100644 --- a/src/main/app-icon.ts +++ b/src/main/app-icon.ts @@ -5,7 +5,6 @@ import { } from 'node:child_process' import { dirname, resolve } from 'node:path' import { app, BrowserWindow, nativeImage } from 'electron' -import { is } from '@electron-toolkit/utils' import classicIcon from '../../resources/icon.png?asset' import classicDevIcon from '../../resources/icon-dev.png?asset' import watercolorIcon from '../../resources/app-icons/orca-watercolor.png?asset' @@ -15,7 +14,7 @@ import blueMacDockIcon from '../../resources/app-icons/orca-blue.png?asset&asarU import { normalizeAppIconId, type AppIconId } from '../shared/app-icon' const APP_ICON_PATHS = { - classic: is.dev ? classicDevIcon : classicIcon, + classic: !app.isPackaged ? classicDevIcon : classicIcon, watercolor: watercolorIcon, blue: blueIcon } satisfies Record @@ -261,7 +260,7 @@ function clearMacCustomIconMetadata(execFile: ExecFile, appBundlePath: string): export function persistMacDockIcon(value: unknown, options: PersistMacDockIconOptions = {}): void { const platform = options.platform ?? process.platform - const isDevApp = options.isDevApp ?? (is.dev || !app.isPackaged) + const isDevApp = options.isDevApp ?? !app.isPackaged if (platform !== 'darwin' || isDevApp) { return } diff --git a/src/main/ipc/app.test.ts b/src/main/ipc/app.test.ts index 092970beed7..c0b249a0670 100644 --- a/src/main/ipc/app.test.ts +++ b/src/main/ipc/app.test.ts @@ -101,10 +101,6 @@ vi.mock('electron', () => ({ } })) -vi.mock('@electron-toolkit/utils', () => ({ - is: { dev: true } -})) - vi.mock('../tray/system-tray', () => ({ destroySystemTray: destroySystemTrayMock, rebuildSystemTrayMenu: rebuildSystemTrayMenuMock diff --git a/src/main/ipc/app.ts b/src/main/ipc/app.ts index 16346ff6e40..43678fc24c2 100644 --- a/src/main/ipc/app.ts +++ b/src/main/ipc/app.ts @@ -5,7 +5,6 @@ import { existsSync } from 'node:fs' import path from 'node:path' import { pathToFileURL } from 'node:url' import { app, BrowserWindow, dialog, ipcMain, type IpcMainInvokeEvent } from 'electron' -import { is } from '@electron-toolkit/utils' import type { AppIdentity } from '../../shared/app-identity' import type { MarkdownDocument } from '../../shared/filesystem-entry-types' import type { FloatingTerminalCwdRequest } from '../../shared/ui-chrome-types' @@ -150,7 +149,7 @@ export function registerAppHandlers(store: Store, options: RegisterAppHandlersOp ipcMain.handle('app:getFeatureWallAssetBaseUrl', (): string => getFeatureWallAssetBaseUrl()) ipcMain.handle('app:getIdentity', (): AppIdentity => { - const identity = getDevInstanceIdentity(is.dev) + const identity = getDevInstanceIdentity(!app.isPackaged) return { name: identity.name, isDev: identity.isDev, diff --git a/src/main/runtime/rpc/methods/orchestration/worker/agent-status-producer-census.test.ts b/src/main/runtime/rpc/methods/orchestration/worker/agent-status-producer-census.test.ts index 8743852aa23..b4c0fda97e3 100644 --- a/src/main/runtime/rpc/methods/orchestration/worker/agent-status-producer-census.test.ts +++ b/src/main/runtime/rpc/methods/orchestration/worker/agent-status-producer-census.test.ts @@ -22,12 +22,6 @@ vi.mock('../../../../../git/worktree', async (importOriginal) => ({ ...(await importOriginal>()), listWorktreesStrict })) -// The push path reaches the dashboard popout window, whose electron re-export cannot load here. -vi.mock('@electron-toolkit/utils', () => ({ - is: { dev: false }, - optimizer: { watchWindowShortcuts: vi.fn() }, - electronApp: { setAppUserModelId: vi.fn() } -})) import type Database from '../../../../../sqlite/sync-database' import type { AgentStatusIpcPayload } from '../../../../../../shared/agent-status-ipc-payload' diff --git a/src/main/startup/browser-process-user-agent-ordering.test.ts b/src/main/startup/browser-process-user-agent-ordering.test.ts index 6fa7b1ccba1..d0633fae704 100644 --- a/src/main/startup/browser-process-user-agent-ordering.test.ts +++ b/src/main/startup/browser-process-user-agent-ordering.test.ts @@ -59,7 +59,6 @@ vi.mock('electron', () => ({ vi.mock('../window/foreground-activation-policy', () => ({ isBackgroundLaunch: mocks.backgroundLaunch })) -vi.mock('@electron-toolkit/utils', () => ({ is: { dev: true } })) vi.mock('./cli-launch-redirect', () => ({ maybeRedirectCliLaunch: () => ({ redirected: false, status: 0 }) })) diff --git a/src/main/startup/codex-hook-startup-wiring.test.ts b/src/main/startup/codex-hook-startup-wiring.test.ts index e15735aa13a..105c2f33299 100644 --- a/src/main/startup/codex-hook-startup-wiring.test.ts +++ b/src/main/startup/codex-hook-startup-wiring.test.ts @@ -13,7 +13,6 @@ const fixture = vi.hoisted(() => { }) vi.mock('electron', () => ({ app: fixture.app, nativeTheme: {} })) -vi.mock('@electron-toolkit/utils', () => ({ is: { dev: false } })) vi.mock('../codex/codex-hook-reconcile', () => ({ startCodexHooks: fixture.startCodexHooks })) vi.mock('../agent-hooks/local-agent-cli-presence', () => ({ hydrateAgentCliShellPath: () => fixture.pathReady diff --git a/src/main/startup/gpu-lifecycle-install-dir-acl-guard.test.ts b/src/main/startup/gpu-lifecycle-install-dir-acl-guard.test.ts index 72821c8f9f3..d816df72f29 100644 --- a/src/main/startup/gpu-lifecycle-install-dir-acl-guard.test.ts +++ b/src/main/startup/gpu-lifecycle-install-dir-acl-guard.test.ts @@ -9,10 +9,10 @@ const { showMessageBox, userData } = vi.hoisted(() => ({ userData: { path: '' } })) -// Why the mocks: gpu-lifecycle's import graph reaches electron and the toolkit's -// electron re-export. Everything below this is the real module under test. +// Why: only Electron is mocked; GPU lifecycle decisions stay real. vi.mock('electron', () => ({ app: { + isPackaged: true, getPath: () => userData.path, getVersion: () => '1.4.184', getGPUFeatureStatus: () => ({}), @@ -26,11 +26,6 @@ vi.mock('electron', () => ({ }, dialog: { showMessageBox } })) -vi.mock('@electron-toolkit/utils', () => ({ - is: { dev: false }, - optimizer: { watchWindowShortcuts: vi.fn() }, - electronApp: { setAppUserModelId: vi.fn() } -})) import { grantsFrom } from './windows-install-dir-acl.test-fixture' import { diff --git a/src/main/startup/main-process-preflight.ts b/src/main/startup/main-process-preflight.ts index 4d98658718a..738c08cfc71 100644 --- a/src/main/startup/main-process-preflight.ts +++ b/src/main/startup/main-process-preflight.ts @@ -1,7 +1,6 @@ import { antigravityHookService } from '../antigravity/hook-service' import { getRelocatedDaemonHost } from '../daemon/daemon-host-relocation' import { app, ipcMain, powerMonitor, session } from 'electron' -import { is } from '@electron-toolkit/utils' import os from 'node:os' import { join } from 'node:path' import { maybeRedirectCliLaunch } from './cli-launch-redirect' @@ -130,6 +129,7 @@ export function runMainProcessPreflight(options: MainProcessPreflightOptions): b } function initializeMainProcessPreflight(options: MainProcessPreflightOptions): boolean { + const isDev = !app.isPackaged // Why first: every step below, recovery and the instance lock included, may resolve userData. ensureWindowsAppDataPath(app) if (runProfileStateRecoveryPreflight()) { @@ -161,7 +161,7 @@ function initializeMainProcessPreflight(options: MainProcessPreflightOptions): b if (state.isServeMode) { reserveServeStdoutForReadiness() } - state.devInstanceIdentity = getDevInstanceIdentity(is.dev) + state.devInstanceIdentity = getDevInstanceIdentity(isDev) state.devAgentHookEndpointNamespace = state.devInstanceIdentity.isDev ? state.devInstanceIdentity.appUserModelId : undefined @@ -208,7 +208,7 @@ function initializeMainProcessPreflight(options: MainProcessPreflightOptions): b // Why before any spawn: `signalProcessTree` is shared with the CLI and relay, so // it can only reach the main-process guard and breadcrumb store once this is registered. installMainProcessTreeKillGate() - configureDevUserDataPath(is.dev) + configureDevUserDataPath(isDev) configureOrcaUserDataPathEnv() // Why these four lines are one step (#16761): the two above decide where userData lives, and // everything below may resolve a path. Installing the accessor any later leaves a window where an @@ -253,8 +253,8 @@ function initializeMainProcessPreflight(options: MainProcessPreflightOptions): b startMainThreadChurnProbe({ extraStats: () => ({ diffCache: settledDiffCache.stats() }) }) // Why: acquire AFTER configureDevUserDataPath — Electron derives lock identity from `userData`, so dev/packaged lock in separate namespaces. // Why dev locks too: two processes on one profile corrupt its stores (PR #1326 / #1312); parallel `pnpm dev` needs ORCA_DEV_USER_DATA_PATH per copy. - const bypass = shouldBypassSingleInstanceLock({ isDev: is.dev, isServeMode: state.isServeMode }) - const skip = shouldSkipSingleInstanceLock({ isDev: is.dev, isServeMode: state.isServeMode }) + const bypass = shouldBypassSingleInstanceLock({ isDev, isServeMode: state.isServeMode }) + const skip = shouldSkipSingleInstanceLock({ isDev, isServeMode: state.isServeMode }) if (bypass) { // Why: diagnostic escape hatch for macOS builds where Electron reports a false lock loss before any app logs exist. logSingleInstanceLockBypass() @@ -271,7 +271,7 @@ function initializeMainProcessPreflight(options: MainProcessPreflightOptions): b // Why: a false-negative lock loss otherwise looks like a silent crash on packaged macOS; `open --stderr` can capture this line. // In dev it is the line `pnpm dev` prints before exiting. logSingleInstanceLockFailure({ - isDevDesktop: is.dev && !state.isServeMode, + isDevDesktop: isDev && !state.isServeMode, userDataPath: app.getPath('userData') }) // Why: a graceful quit is deferred pre-ready, so this launch would still walk into Linux display init and SIGSEGV (#11935). @@ -325,7 +325,7 @@ function initializeMainProcessPreflight(options: MainProcessPreflightOptions): b setSpeechServiceFactories(electronSpeechServiceFactories) setWorktreeWatcherRemoval(desktopWorktreeWatcherRemoval) // Why: couple to dev-parent only for electron-vite desktop runs; `orca serve`'s parent (CLI shim/background shell) isn't the intended server lifetime. - const shouldCoupleToDevParent = is.dev && !state.isServeMode + const shouldCoupleToDevParent = isDev && !state.isServeMode installDevParentDisconnectQuit(shouldCoupleToDevParent) installDevParentWatchdog(shouldCoupleToDevParent) installDevParentSignalQuit(shouldCoupleToDevParent) diff --git a/src/main/startup/main-process-ready-duplicate-pty-repair.test.ts b/src/main/startup/main-process-ready-duplicate-pty-repair.test.ts index 4d72c9bf100..148eba609be 100644 --- a/src/main/startup/main-process-ready-duplicate-pty-repair.test.ts +++ b/src/main/startup/main-process-ready-duplicate-pty-repair.test.ts @@ -39,7 +39,6 @@ vi.mock('electron', () => ({ app: { isPackaged: false, on: vi.fn(), once: vi.fn(), getPath: () => fixture.userData }, nativeTheme: {} })) -vi.mock('@electron-toolkit/utils', () => ({ is: { dev: false } })) vi.mock('./main-process-state', () => ({ mainProcessState: fixture.state })) vi.mock('../runtime/orca-runtime', () => ({ OrcaRuntimeService: class { diff --git a/src/main/startup/main-process-ready-foundation.ts b/src/main/startup/main-process-ready-foundation.ts index 1e4f48f3e1a..bfcbb91749a 100644 --- a/src/main/startup/main-process-ready-foundation.ts +++ b/src/main/startup/main-process-ready-foundation.ts @@ -1,5 +1,4 @@ import { app, session } from 'electron' -import { electronApp, is } from '@electron-toolkit/utils' import { applyBackgroundActivationPolicy } from '../window/foreground-activation-policy' import { applyElectronProxySettings } from '../network/proxy-settings' import { installElectronProxyRequestGuard } from '../network/electron-proxy-request-guard' @@ -97,7 +96,9 @@ export async function initializeReadyFoundation(): Promise { if (!identity) { throw new Error('Development identity is unavailable') } - electronApp.setAppUserModelId(identity.appUserModelId) + if (process.platform === 'win32') { + app.setAppUserModelId(app.isPackaged ? identity.appUserModelId : process.execPath) + } // Why: names the app menu/About panel. Dev already applied this pre-ready (see the // safeStorage note above); this call stays unconditional so packaged builds keep their // existing post-ready rename, which lands after the Keychain name is already resolved. @@ -184,7 +185,7 @@ export async function initializeReadyFoundation(): Promise { dataFile: profile.dataFile, force: process.env.ORCA_ALWAYS_REPORT_SECRET_PROTECTION === '1', deferUntilFirstWindow: !state.isServeMode, - skipInDevelopment: is.dev + skipInDevelopment: !app.isPackaged }) // Why here: the host key store is a sidecar of the same profile, and every SSH connect consults // it. Left unbound it reports nothing trusted, which is safe but silently discards our own @@ -267,7 +268,7 @@ export async function initializeReadyFoundation(): Promise { } }) applyAppIcon(store.getSettings().appIcon) - if (shouldSuppressDevEducation({ isDev: is.dev })) { + if (shouldSuppressDevEducation({ isDev: !app.isPackaged })) { suppressDevEducationForStore(store) } // Why: the partition installer reads the proxy through this resolver, so register it before sessions materialize. diff --git a/src/main/startup/main-process-ready-identity-write.test.ts b/src/main/startup/main-process-ready-identity-write.test.ts index 1ece1b6e523..5b95efca50f 100644 --- a/src/main/startup/main-process-ready-identity-write.test.ts +++ b/src/main/startup/main-process-ready-identity-write.test.ts @@ -1,10 +1,11 @@ import { mkdtempSync, writeFileSync } from 'node:fs' import { tmpdir } from 'node:os' import { join } from 'node:path' -import { beforeAll, beforeEach, describe, expect, it, vi } from 'vitest' +import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest' import type * as DurableFileWrite from '../durable-file-write' import { JIRA_IMAGE_SCHEME } from '../../shared/jira-attachment-image' +const ORIGINAL_PLATFORM = process.platform const ORCA_PROFILE_ID = 'local-default' const RETIRED_PROFILE_ID = '11111111-1111-4111-8111-111111111111' @@ -12,6 +13,8 @@ const mocks = vi.hoisted(() => ({ // Assigned in beforeAll; the factories below read them lazily, so real directories exist by the // time ready composition resolves the canonical userData path and the active profile directory. userDataPath: '', + isPackaged: false, + setAppUserModelId: vi.fn(), profileDirectory: '', state: { devInstanceIdentity: { appUserModelId: 'app.id', appName: 'Orca' }, @@ -50,7 +53,10 @@ vi.mock('electron', () => ({ setName: vi.fn(), getPath: vi.fn(() => mocks.userDataPath), getVersion: vi.fn(() => '1.0.0'), - isPackaged: false + get isPackaged() { + return mocks.isPackaged + }, + setAppUserModelId: mocks.setAppUserModelId }, session: { defaultSession: {}, @@ -65,10 +71,6 @@ vi.mock('electron', () => ({ })) } })) -vi.mock('@electron-toolkit/utils', () => ({ - electronApp: { setAppUserModelId: vi.fn() }, - is: { dev: false } -})) vi.mock('./main-process-state', () => ({ mainProcessState: mocks.state })) vi.mock('../persistence', () => ({ Store: class { @@ -145,6 +147,7 @@ vi.mock('../pty/legacy-terminal-shim-dir', () => ({ neutralizeLegacyTerminalShim vi.mock('./windows-shell-path-hydration', () => ({ createWindowsShellPathHydration: () => ({ configure: vi.fn(), + hydrate: vi.fn(async () => {}), whenReady: Promise.resolve() }) })) @@ -212,6 +215,7 @@ vi.mock('../crash-reporting/durable-crash-breadcrumb', () => ({ vi.mock('./main-window-actions', () => ({ syncMacMenuBarIcon: vi.fn() })) vi.mock('./gpu-lifecycle', () => ({ updateGpuAccelerationAboutPanel: vi.fn() })) vi.mock('../cli/wsl-cli-registration-reconciliation', () => ({ + logWslCliReconciliationResults: vi.fn(), reconcileManagedWslCliRegistrations: vi.fn(async () => []) })) vi.mock('./wsl-cli-reconciliation-startup-barrier', () => ({ @@ -313,6 +317,8 @@ describe('ready-phase browser identity authority', () => { beforeEach(() => { vi.resetModules() + mocks.isPackaged = false + mocks.setAppUserModelId.mockClear() mocks.openMainWindow.mockClear() mocks.handleProtocol.mockClear() mocks.runtimeRpcStart.mockClear() @@ -320,6 +326,32 @@ describe('ready-phase browser identity authority', () => { mocks.state.isServeMode = false }) + afterEach(() => { + Object.defineProperty(process, 'platform', { value: ORIGINAL_PLATFORM }) + }) + + it.each([ + { platform: 'win32', isPackaged: true, appId: 'app.id' }, + { platform: 'win32', isPackaged: false, appId: process.execPath }, + { platform: 'darwin', isPackaged: true, appId: null }, + { platform: 'linux', isPackaged: true, appId: null } + ])( + 'sets Windows app identity on $platform (packaged=$isPackaged)', + async ({ platform, isPackaged, appId }) => { + seedIdentityRecord('clean', true) + mocks.isPackaged = isPackaged + Object.defineProperty(process, 'platform', { value: platform }) + + await runReady() + + if (appId === null) { + expect(mocks.setAppUserModelId).not.toHaveBeenCalled() + } else { + expect(mocks.setAppUserModelId).toHaveBeenCalledExactlyOnceWith(appId) + } + } + ) + // The bug: ready used to mirror a retired per-profile setting into the root record, so switching // from a native profile to a clean one started the clean profile in native. The root record read // before ready is the only authority now, and ready must not rewrite it in either direction — diff --git a/src/main/startup/main-process-ready-runtime.ts b/src/main/startup/main-process-ready-runtime.ts index fd07a68723a..28e9916311e 100644 --- a/src/main/startup/main-process-ready-runtime.ts +++ b/src/main/startup/main-process-ready-runtime.ts @@ -1,7 +1,6 @@ import { app, nativeTheme } from 'electron' import { randomUUID } from 'node:crypto' import { performance } from 'node:perf_hooks' -import { is } from '@electron-toolkit/utils' import { StarNagService } from '../star-nag/service' import { AgentBrowserBridge } from '../browser/agent-browser-bridge' import { EmulatorBridge } from '../emulator/emulator-bridge' @@ -116,7 +115,7 @@ export async function initializeReadyRuntimeServices(): Promise { return state.codexRuntimeHome.resolveHostCodexHomePathForLaunchReadOnly() } }) - if (shouldInstallManagedHooks(is.dev)) { + if (shouldInstallManagedHooks(!app.isPackaged)) { reconcileStartupManagedAgentHooks({ getSettings: () => store.getSettings(), isQuitting: () => state.isQuitting, diff --git a/src/main/startup/main-process-runtime-launch-activation.test.ts b/src/main/startup/main-process-runtime-launch-activation.test.ts index 848e19d397d..69dd5e5df0a 100644 --- a/src/main/startup/main-process-runtime-launch-activation.test.ts +++ b/src/main/startup/main-process-runtime-launch-activation.test.ts @@ -14,7 +14,6 @@ const launchHooks = vi.hoisted(() => ({ })) vi.mock('electron', () => ({ app: electronApp, powerMonitor: { on: vi.fn() } })) -vi.mock('@electron-toolkit/utils', () => ({ is: { dev: false } })) vi.mock('../orca-profiles/profile-cloud-auth-config', () => ({ getOrcaCloudAuthConfig: () => ({ configured: false }) })) diff --git a/src/main/startup/main-process-runtime-launch.ts b/src/main/startup/main-process-runtime-launch.ts index 94dc70f60b2..c8cdda561d1 100644 --- a/src/main/startup/main-process-runtime-launch.ts +++ b/src/main/startup/main-process-runtime-launch.ts @@ -1,7 +1,6 @@ import { app, type BrowserWindow } from 'electron' import { ORCA_LAYOUT_OWNER_IS_MAIN } from '../../shared/layout-owner-switch' import { placeUnshownLiveTerminalsBestEffort } from '../runtime/terminal/adoption/unshown-live-terminal-placement' -import { is } from '@electron-toolkit/utils' import { getCanonicalUserDataPath, migrateMobilePairingDataToCanonicalUserDataPath @@ -81,7 +80,7 @@ function installRuntimeRpc( throw new Error(`Invalid ORCA_E2E_RUNTIME_WS_PORT value: ${requestedE2EWsPort}`) } // Why: pin dev to 6769 so `pnpm dev` doesn't race packaged Orca on 6768 and fall back to a random port, breaking deterministic mobile pairing/repro (STA-1511). - const devWsPort = is.dev && !isE2E ? 6769 : undefined + const devWsPort = !app.isPackaged && !isE2E ? 6769 : undefined const runtimeRpc = new OrcaRuntimeRpcServer({ runtime, // Why: mobile pairing needs the stable pre-setName() path (getCanonicalUserDataPath), not a late app.getPath('userData') that drops paired devices across restarts. diff --git a/src/main/updater-linux-package-recovery-actions.test.ts b/src/main/updater-linux-package-recovery-actions.test.ts index 6b48d0cc4fc..e79c66b25ea 100644 --- a/src/main/updater-linux-package-recovery-actions.test.ts +++ b/src/main/updater-linux-package-recovery-actions.test.ts @@ -67,7 +67,6 @@ vi.mock('electron', () => ({ vi.mock('electron-updater', () => ({ autoUpdater: autoUpdaterMock })) vi.mock('./electron-updater-loader', () => ({ loadElectronAutoUpdater: () => autoUpdaterMock })) -vi.mock('@electron-toolkit/utils', () => ({ is: { dev: false } })) vi.mock('./ipc/pty/kill-all', () => ({ killAllPty: vi.fn() })) vi.mock('./updater-changelog', () => ({ fetchChangelog: vi.fn().mockResolvedValue(null) })) vi.mock('./updater-nudge', () => ({ diff --git a/src/main/updater-sqlite-profile-downgrade.test.ts b/src/main/updater-sqlite-profile-downgrade.test.ts index 1053bd88512..f7a2934ef71 100644 --- a/src/main/updater-sqlite-profile-downgrade.test.ts +++ b/src/main/updater-sqlite-profile-downgrade.test.ts @@ -7,7 +7,6 @@ const { appMock, autoUpdaterMock, chooseLocalBuildMock, moduleFactories, resetUp vi.mock('electron', () => moduleFactories.electron()) vi.mock('electron-updater', () => moduleFactories.electronUpdater()) vi.mock('./electron-updater-loader', () => moduleFactories.electronUpdaterLoader()) -vi.mock('@electron-toolkit/utils', () => moduleFactories.electronToolkitUtils()) vi.mock('./ipc/pty/kill-all', () => moduleFactories.ptyKillAll()) vi.mock('./linux-update-package-type', () => moduleFactories.linuxUpdatePackageType()) vi.mock('./updater-lifecycle-diagnostics', () => moduleFactories.updaterLifecycleDiagnostics()) diff --git a/src/main/updater-test-harness.ts b/src/main/updater-test-harness.ts index 11a94a460b4..1db4f5f6ba9 100644 --- a/src/main/updater-test-harness.ts +++ b/src/main/updater-test-harness.ts @@ -45,7 +45,6 @@ type UpdaterModuleFactories = { } electronUpdater: () => { autoUpdater: AutoUpdaterMock } electronUpdaterLoader: () => { loadElectronAutoUpdater: () => AutoUpdaterMock } - electronToolkitUtils: () => { is: { dev: boolean } } ptyKillAll: () => { killAllPty: UpdaterSpy } linuxUpdatePackageType: () => { getLinuxPackageType: Mock<() => LinuxPackageType> @@ -72,7 +71,6 @@ export type UpdaterMocks = { browserWindowMock: { getAllWindows: Mock<() => unknown[]> } nativeUpdaterMock: { on: UpdaterSpy } autoUpdaterMock: AutoUpdaterMock - isMock: { dev: boolean } killAllPtyMock: UpdaterSpy powerMonitorOnMock: UpdaterSpy getLinuxPackageTypeMock: Mock<() => LinuxPackageType> @@ -206,7 +204,6 @@ export function createUpdaterMocks(): UpdaterMocks { const nativeUpdaterMock = { on: vi.fn() } - const isMock = { dev: false } const killAllPtyMock = vi.fn() const powerMonitorOnMock = vi.fn() const getLinuxRootPackageTypeMock = vi.fn<() => 'deb' | 'rpm' | null>(() => null) @@ -237,7 +234,6 @@ export function createUpdaterMocks(): UpdaterMocks { }), electronUpdater: () => ({ autoUpdater: autoUpdaterMock }), electronUpdaterLoader: () => ({ loadElectronAutoUpdater: loadGenerationScopedAutoUpdater }), - electronToolkitUtils: () => ({ is: isMock }), ptyKillAll: () => ({ killAllPty: killAllPtyMock }), // Why: only the marker resolver is faked so the real artifact capture/redaction path stays under test. linuxUpdatePackageType: () => ({ @@ -282,7 +278,6 @@ export function createUpdaterMocks(): UpdaterMocks { appMock.getVersion.mockReturnValue('1.0.51') appMock.quit.mockReset() appMock.isPackaged = true - isMock.dev = false killAllPtyMock.mockReset() armExitWatchdogMock.mockReset() disarmExitWatchdogMock.mockReset() @@ -319,7 +314,6 @@ export function createUpdaterMocks(): UpdaterMocks { browserWindowMock, nativeUpdaterMock, autoUpdaterMock, - isMock, killAllPtyMock, powerMonitorOnMock, getLinuxPackageTypeMock, diff --git a/src/main/updater.build-channel-selection.test.ts b/src/main/updater.build-channel-selection.test.ts index 6932143ea94..1b1a6a5e79c 100644 --- a/src/main/updater.build-channel-selection.test.ts +++ b/src/main/updater.build-channel-selection.test.ts @@ -14,7 +14,6 @@ const { vi.mock('electron', () => moduleFactories.electron()) vi.mock('electron-updater', () => moduleFactories.electronUpdater()) vi.mock('./electron-updater-loader', () => moduleFactories.electronUpdaterLoader()) -vi.mock('@electron-toolkit/utils', () => moduleFactories.electronToolkitUtils()) vi.mock('./ipc/pty/kill-all', () => moduleFactories.ptyKillAll()) vi.mock('./linux-update-package-type', () => moduleFactories.linuxUpdatePackageType()) vi.mock('./updater-lifecycle-diagnostics', () => moduleFactories.updaterLifecycleDiagnostics()) diff --git a/src/main/updater.check-failure.test.ts b/src/main/updater.check-failure.test.ts index 53f3359686c..d9f52bcd169 100644 --- a/src/main/updater.check-failure.test.ts +++ b/src/main/updater.check-failure.test.ts @@ -8,7 +8,7 @@ const { netFetchMock, netRequestMock } = vi.hoisted(() => ({ netRequestMock: vi.fn() })) -const { appMock, browserWindowMock, nativeUpdaterMock, autoUpdaterMock, isMock, killAllPtyMock } = +const { appMock, browserWindowMock, nativeUpdaterMock, autoUpdaterMock, killAllPtyMock } = vi.hoisted(() => { const appEventHandlers = new Map void)[]>() const eventHandlers = new Map void)[]>() @@ -79,7 +79,7 @@ const { appMock, browserWindowMock, nativeUpdaterMock, autoUpdaterMock, isMock, on: vi.fn() }, autoUpdaterMock, - isMock: { dev: false }, + killAllPtyMock: vi.fn() } }) @@ -100,10 +100,6 @@ vi.mock('./electron-updater-loader', () => ({ loadElectronAutoUpdater: () => autoUpdaterMock })) -vi.mock('@electron-toolkit/utils', () => ({ - is: isMock -})) - vi.mock('./ipc/pty/kill-all', () => ({ killAllPty: killAllPtyMock })) vi.mock('./updater-nudge', () => ({ @@ -178,7 +174,7 @@ describe('updater check failure handling', () => { appMock.getVersion.mockReturnValue('1.0.51') appMock.quit.mockReset() appMock.isPackaged = true - isMock.dev = false + killAllPtyMock.mockReset() vi.unstubAllGlobals() vi.useRealTimers() diff --git a/src/main/updater.check-preflight.test.ts b/src/main/updater.check-preflight.test.ts index 6a4054fe343..a55338c265c 100644 --- a/src/main/updater.check-preflight.test.ts +++ b/src/main/updater.check-preflight.test.ts @@ -14,7 +14,6 @@ const { vi.mock('electron', () => moduleFactories.electron()) vi.mock('electron-updater', () => moduleFactories.electronUpdater()) vi.mock('./electron-updater-loader', () => moduleFactories.electronUpdaterLoader()) -vi.mock('@electron-toolkit/utils', () => moduleFactories.electronToolkitUtils()) vi.mock('./ipc/pty/kill-all', () => moduleFactories.ptyKillAll()) vi.mock('./linux-update-package-type', () => moduleFactories.linuxUpdatePackageType()) vi.mock('./updater-lifecycle-diagnostics', () => moduleFactories.updaterLifecycleDiagnostics()) diff --git a/src/main/updater.check-settlement.test.ts b/src/main/updater.check-settlement.test.ts index 82d9aa144ac..7269ffd48fe 100644 --- a/src/main/updater.check-settlement.test.ts +++ b/src/main/updater.check-settlement.test.ts @@ -13,7 +13,6 @@ const { vi.mock('electron', () => moduleFactories.electron()) vi.mock('electron-updater', () => moduleFactories.electronUpdater()) vi.mock('./electron-updater-loader', () => moduleFactories.electronUpdaterLoader()) -vi.mock('@electron-toolkit/utils', () => moduleFactories.electronToolkitUtils()) vi.mock('./ipc/pty/kill-all', () => moduleFactories.ptyKillAll()) vi.mock('./linux-update-package-type', () => moduleFactories.linuxUpdatePackageType()) vi.mock('./updater-lifecycle-diagnostics', () => moduleFactories.updaterLifecycleDiagnostics()) diff --git a/src/main/updater.feed-attempt-lifetime.test.ts b/src/main/updater.feed-attempt-lifetime.test.ts index df278023d11..c323a599e53 100644 --- a/src/main/updater.feed-attempt-lifetime.test.ts +++ b/src/main/updater.feed-attempt-lifetime.test.ts @@ -7,7 +7,6 @@ const { autoUpdaterMock, fetchNewerReleaseTagsMock, moduleFactories, resetUpdate vi.mock('electron', () => moduleFactories.electron()) vi.mock('electron-updater', () => moduleFactories.electronUpdater()) vi.mock('./electron-updater-loader', () => moduleFactories.electronUpdaterLoader()) -vi.mock('@electron-toolkit/utils', () => moduleFactories.electronToolkitUtils()) vi.mock('./ipc/pty/kill-all', () => moduleFactories.ptyKillAll()) vi.mock('./linux-update-package-type', () => moduleFactories.linuxUpdatePackageType()) vi.mock('./updater-lifecycle-diagnostics', () => moduleFactories.updaterLifecycleDiagnostics()) diff --git a/src/main/updater.headless-serve-install.test.ts b/src/main/updater.headless-serve-install.test.ts index 1c686dd7899..7fb4aa27b76 100644 --- a/src/main/updater.headless-serve-install.test.ts +++ b/src/main/updater.headless-serve-install.test.ts @@ -95,7 +95,6 @@ vi.mock('./linux-update-package-type', () => ({ getLinuxRootPackageType: () => null, isExternallyManagedLinuxInstall: () => false })) -vi.mock('@electron-toolkit/utils', () => ({ is: { dev: false } })) vi.mock('./ipc/pty/kill-all', () => ({ killAllPty: killAllPtyMock })) vi.mock('./updater-changelog', () => ({ fetchChangelog: vi.fn().mockResolvedValue(null) })) vi.mock('./updater-nudge', () => ({ diff --git a/src/main/updater.install-failure-cause.test.ts b/src/main/updater.install-failure-cause.test.ts index e061ff682b6..9b94fd44cd6 100644 --- a/src/main/updater.install-failure-cause.test.ts +++ b/src/main/updater.install-failure-cause.test.ts @@ -9,7 +9,6 @@ const { browserWindowMock, nativeUpdaterMock, autoUpdaterMock, - isMock, killAllPtyMock, recordUpdaterLifecycleMock } = vi.hoisted(() => { @@ -79,7 +78,7 @@ const { browserWindowMock: { getAllWindows: vi.fn(() => []) }, nativeUpdaterMock: { on: vi.fn() }, autoUpdaterMock, - isMock: { dev: false }, + killAllPtyMock: vi.fn(), recordUpdaterLifecycleMock: vi.fn() } @@ -98,7 +97,6 @@ vi.mock('electron-updater', () => ({ autoUpdater: autoUpdaterMock })) vi.mock('./electron-updater-loader', () => ({ loadElectronAutoUpdater: () => autoUpdaterMock })) -vi.mock('@electron-toolkit/utils', () => ({ is: isMock })) vi.mock('./ipc/pty/kill-all', () => ({ killAllPty: killAllPtyMock })) vi.mock('./updater-changelog', () => ({ fetchChangelog: vi.fn().mockResolvedValue(null) @@ -196,7 +194,7 @@ describe('quitAndInstall failure carries the updater cause', () => { appMock.getVersion.mockReturnValue('1.4.162') appMock.quit.mockReset() appMock.isPackaged = true - isMock.dev = false + killAllPtyMock.mockReset() recordUpdaterLifecycleMock.mockReset() Object.defineProperty(process, 'platform', { diff --git a/src/main/updater.linux-externally-managed.test.ts b/src/main/updater.linux-externally-managed.test.ts index f0a78fb4262..ef27fda2fa2 100644 --- a/src/main/updater.linux-externally-managed.test.ts +++ b/src/main/updater.linux-externally-managed.test.ts @@ -16,7 +16,6 @@ const { vi.mock('electron', () => moduleFactories.electron()) vi.mock('electron-updater', () => moduleFactories.electronUpdater()) vi.mock('./electron-updater-loader', () => moduleFactories.electronUpdaterLoader()) -vi.mock('@electron-toolkit/utils', () => moduleFactories.electronToolkitUtils()) vi.mock('./ipc/pty/kill-all', () => moduleFactories.ptyKillAll()) vi.mock('./linux-update-package-type', () => moduleFactories.linuxUpdatePackageType()) vi.mock('./updater-lifecycle-diagnostics', () => moduleFactories.updaterLifecycleDiagnostics()) diff --git a/src/main/updater.linux-root-package-install.test.ts b/src/main/updater.linux-root-package-install.test.ts index 29a1e611a37..6ae9794d83e 100644 --- a/src/main/updater.linux-root-package-install.test.ts +++ b/src/main/updater.linux-root-package-install.test.ts @@ -21,7 +21,6 @@ const { vi.mock('electron', () => moduleFactories.electron()) vi.mock('electron-updater', () => moduleFactories.electronUpdater()) vi.mock('./electron-updater-loader', () => moduleFactories.electronUpdaterLoader()) -vi.mock('@electron-toolkit/utils', () => moduleFactories.electronToolkitUtils()) vi.mock('./ipc/pty/kill-all', () => moduleFactories.ptyKillAll()) vi.mock('./linux-update-package-type', () => moduleFactories.linuxUpdatePackageType()) vi.mock('./updater-lifecycle-diagnostics', () => moduleFactories.updaterLifecycleDiagnostics()) diff --git a/src/main/updater.mac-install.test.ts b/src/main/updater.mac-install.test.ts index ac02d0a69a7..b96b589b6f4 100644 --- a/src/main/updater.mac-install.test.ts +++ b/src/main/updater.mac-install.test.ts @@ -8,7 +8,6 @@ const { nativeUpdaterMock, autoUpdaterMock, shellMock, - isMock, killAllPtyMock, getMacUpdateRunningInstancesMock, prepareShipItStagingMock, @@ -87,7 +86,7 @@ const { shellMock: { openExternal: vi.fn() }, - isMock: { dev: false }, + getMacUpdateRunningInstancesMock: vi.fn(async (): Promise => []), recoverBrowserSidecarsMock: vi.fn(async (_executable: string, pids: number[]) => pids), describeBrowserBlockersMock: vi.fn(async (_executable: string, pids: number[]) => @@ -115,10 +114,6 @@ vi.mock('./electron-updater-loader', () => ({ loadElectronAutoUpdater: () => autoUpdaterMock })) -vi.mock('@electron-toolkit/utils', () => ({ - is: isMock -})) - vi.mock('./ipc/pty/kill-all', () => ({ killAllPty: killAllPtyMock })) vi.mock('./updater-changelog', () => ({ @@ -182,7 +177,7 @@ describe('updater mac install handoff', () => { appMock.getVersion.mockReturnValue('1.0.51') appMock.quit.mockReset() appMock.isPackaged = true - isMock.dev = false + killAllPtyMock.mockReset() getMacUpdateRunningInstancesMock.mockReset().mockResolvedValue([]) recoverBrowserSidecarsMock diff --git a/src/main/updater.nudge-campaign.test.ts b/src/main/updater.nudge-campaign.test.ts index 6221c26599c..67d74df1314 100644 --- a/src/main/updater.nudge-campaign.test.ts +++ b/src/main/updater.nudge-campaign.test.ts @@ -14,7 +14,6 @@ const { vi.mock('electron', () => moduleFactories.electron()) vi.mock('electron-updater', () => moduleFactories.electronUpdater()) vi.mock('./electron-updater-loader', () => moduleFactories.electronUpdaterLoader()) -vi.mock('@electron-toolkit/utils', () => moduleFactories.electronToolkitUtils()) vi.mock('./ipc/pty/kill-all', () => moduleFactories.ptyKillAll()) vi.mock('./linux-update-package-type', () => moduleFactories.linuxUpdatePackageType()) vi.mock('./updater-lifecycle-diagnostics', () => moduleFactories.updaterLifecycleDiagnostics()) diff --git a/src/main/updater.prerelease-fallback.test.ts b/src/main/updater.prerelease-fallback.test.ts index 64b7c6dfd9b..083121d8453 100644 --- a/src/main/updater.prerelease-fallback.test.ts +++ b/src/main/updater.prerelease-fallback.test.ts @@ -7,7 +7,6 @@ const { appMock, autoUpdaterMock, fetchNewerReleaseTagsMock, moduleFactories, re vi.mock('electron', () => moduleFactories.electron()) vi.mock('electron-updater', () => moduleFactories.electronUpdater()) vi.mock('./electron-updater-loader', () => moduleFactories.electronUpdaterLoader()) -vi.mock('@electron-toolkit/utils', () => moduleFactories.electronToolkitUtils()) vi.mock('./ipc/pty/kill-all', () => moduleFactories.ptyKillAll()) vi.mock('./linux-update-package-type', () => moduleFactories.linuxUpdatePackageType()) vi.mock('./updater-lifecycle-diagnostics', () => moduleFactories.updaterLifecycleDiagnostics()) diff --git a/src/main/updater.publishing-window-feed.test.ts b/src/main/updater.publishing-window-feed.test.ts index 2e90d9eaefd..95a590aa97e 100644 --- a/src/main/updater.publishing-window-feed.test.ts +++ b/src/main/updater.publishing-window-feed.test.ts @@ -14,7 +14,6 @@ const { vi.mock('electron', () => moduleFactories.electron()) vi.mock('electron-updater', () => moduleFactories.electronUpdater()) vi.mock('./electron-updater-loader', () => moduleFactories.electronUpdaterLoader()) -vi.mock('@electron-toolkit/utils', () => moduleFactories.electronToolkitUtils()) vi.mock('./ipc/pty/kill-all', () => moduleFactories.ptyKillAll()) vi.mock('./linux-update-package-type', () => moduleFactories.linuxUpdatePackageType()) vi.mock('./updater-lifecycle-diagnostics', () => moduleFactories.updaterLifecycleDiagnostics()) diff --git a/src/main/updater.quit-and-install.test.ts b/src/main/updater.quit-and-install.test.ts index 6b8e598e796..6d2c2deecad 100644 --- a/src/main/updater.quit-and-install.test.ts +++ b/src/main/updater.quit-and-install.test.ts @@ -20,7 +20,6 @@ const { launchPathScope } = vi.hoisted(() => ({ vi.mock('electron', () => moduleFactories.electron()) vi.mock('electron-updater', () => moduleFactories.electronUpdater()) vi.mock('./electron-updater-loader', () => moduleFactories.electronUpdaterLoader()) -vi.mock('@electron-toolkit/utils', () => moduleFactories.electronToolkitUtils()) vi.mock('./ipc/pty/kill-all', () => moduleFactories.ptyKillAll()) vi.mock('./linux-update-package-type', () => moduleFactories.linuxUpdatePackageType()) vi.mock('./updater-lifecycle-diagnostics', () => moduleFactories.updaterLifecycleDiagnostics()) diff --git a/src/main/updater.startup-scheduling.test.ts b/src/main/updater.startup-scheduling.test.ts index 5c7ae53793b..d7f78ded6fa 100644 --- a/src/main/updater.startup-scheduling.test.ts +++ b/src/main/updater.startup-scheduling.test.ts @@ -4,7 +4,6 @@ import { loadUpdaterModule, warmUpdaterModule } from './updater-test-module-load const { appMock, autoUpdaterMock, - isMock, powerMonitorOnMock, fetchNudgeMock, shouldApplyNudgeMock, @@ -15,7 +14,6 @@ const { vi.mock('electron', () => moduleFactories.electron()) vi.mock('electron-updater', () => moduleFactories.electronUpdater()) vi.mock('./electron-updater-loader', () => moduleFactories.electronUpdaterLoader()) -vi.mock('@electron-toolkit/utils', () => moduleFactories.electronToolkitUtils()) vi.mock('./ipc/pty/kill-all', () => moduleFactories.ptyKillAll()) vi.mock('./linux-update-package-type', () => moduleFactories.linuxUpdatePackageType()) vi.mock('./updater-lifecycle-diagnostics', () => moduleFactories.updaterLifecycleDiagnostics()) @@ -35,7 +33,7 @@ describe('updater', () => { }) it('does not load or configure electron-updater during dev setup', async () => { - isMock.dev = true + appMock.isPackaged = false const mainWindow = { webContents: { send: vi.fn() } } const { setupAutoUpdater } = await loadUpdaterModule() diff --git a/src/main/updater/updater-build-selection.ts b/src/main/updater/updater-build-selection.ts index 878a6f2ff46..aeab8b61250 100644 --- a/src/main/updater/updater-build-selection.ts +++ b/src/main/updater/updater-build-selection.ts @@ -1,5 +1,4 @@ import { app } from 'electron' -import { is } from '@electron-toolkit/utils' import { DEV_CHANNEL_PLATFORM_LABEL, getVersionChannel, @@ -90,7 +89,7 @@ export abstract class UpdaterBuildSelection extends UpdaterMenuChecks { /** Pins the updater at one exact release tag and checks it, so a dev can move to any published build on any channel — including an older one. */ protected async checkForPinnedBuild(channel: ReleaseChannel, tag: string): Promise { - if (!app.isPackaged || is.dev) { + if (!app.isPackaged) { this.sendStatus({ state: 'not-available', userInitiated: true }) return } diff --git a/src/main/updater/updater-menu-checks.ts b/src/main/updater/updater-menu-checks.ts index f6710d555b0..739bd6c1939 100644 --- a/src/main/updater/updater-menu-checks.ts +++ b/src/main/updater/updater-menu-checks.ts @@ -1,5 +1,4 @@ import { app } from 'electron' -import { is } from '@electron-toolkit/utils' import { isMacInstallRequested } from '../updater-mac-install' import type { UpdateCheckOptions } from '../../shared/update-status-types' import type { ReleaseChannel } from '../../shared/release-channel' @@ -15,7 +14,7 @@ export abstract class UpdaterMenuChecks extends UpdaterScheduling { ) { return } - if (!app.isPackaged || is.dev) { + if (!app.isPackaged) { this.sendStatus({ state: 'not-available', userInitiated: true }) return } diff --git a/src/main/updater/updater-nudge.ts b/src/main/updater/updater-nudge.ts index 765af67cd53..4d2109b3947 100644 --- a/src/main/updater/updater-nudge.ts +++ b/src/main/updater/updater-nudge.ts @@ -1,5 +1,4 @@ import { app } from 'electron' -import { is } from '@electron-toolkit/utils' import { fetchNudge, shouldApplyNudge } from '../updater-nudge' import { NUDGE_ACTIVATION_COOLDOWN_MS, NUDGE_POLL_INTERVAL_MS } from './updater-state' import { UpdaterBuildSelection } from './updater-build-selection' @@ -7,7 +6,7 @@ import { UpdaterBuildSelection } from './updater-build-selection' /** Polls update campaigns and exposes their dismissal actions. */ export abstract class UpdaterNudge extends UpdaterBuildSelection { protected async checkForUpdateNudge(): Promise { - if (!app.isPackaged || is.dev) { + if (!app.isPackaged) { return } if (this.nudgeCheckInFlight) { diff --git a/src/main/updater/updater-remote-status.ts b/src/main/updater/updater-remote-status.ts index fc34d40b6d3..f899522acdd 100644 --- a/src/main/updater/updater-remote-status.ts +++ b/src/main/updater/updater-remote-status.ts @@ -1,5 +1,4 @@ import { app } from 'electron' -import { is } from '@electron-toolkit/utils' import type { UpdateCheckOptions, UpdateStatus } from '../../shared/update-status-types' import type { RemoteServerUpdateInstallResult, @@ -18,7 +17,7 @@ export abstract class UpdaterRemoteStatus extends UpdaterNudge { } protected getRemoteServerUpdateSupport(): RemoteServerUpdateSupport { - if (!app.isPackaged || is.dev) { + if (!app.isPackaged) { return { installMode: this.updateInstallMode, automatic: false, diff --git a/src/main/updater/updater-scheduling.ts b/src/main/updater/updater-scheduling.ts index 70993c61ff2..54cf749f703 100644 --- a/src/main/updater/updater-scheduling.ts +++ b/src/main/updater/updater-scheduling.ts @@ -1,5 +1,4 @@ import { app } from 'electron' -import { is } from '@electron-toolkit/utils' import { isMacInstallRequested } from '../updater-mac-install' import { withUpdaterSpan } from '../observability/instrumentation' import { @@ -65,7 +64,7 @@ export abstract class UpdaterScheduling extends UpdaterCheckFailure { if (this.backgroundCheckLaunchPending || this.currentStatus.state === 'checking') { return false } - if (!app.isPackaged || is.dev) { + if (!app.isPackaged) { this.sendStatus({ state: 'not-available' }) return false } diff --git a/src/main/updater/updater-setup.ts b/src/main/updater/updater-setup.ts index e735a4279b7..aa57f500b66 100644 --- a/src/main/updater/updater-setup.ts +++ b/src/main/updater/updater-setup.ts @@ -1,6 +1,5 @@ import { app, powerMonitor } from 'electron' import type { BrowserWindow } from 'electron' -import { is } from '@electron-toolkit/utils' import type { ReleaseBuild, ReleaseChannel } from '../../shared/release-channel' import type { ReleaseBuildListOptions } from '../updater-release-build-cache' import type { @@ -137,10 +136,7 @@ export class UpdaterSetup extends UpdaterDownloadInstall { this.sendErrorStatus(`The server update did not complete: ${serveHandoffFailure}`, true) } - if (!app.isPackaged && !is.dev) { - return - } - if (is.dev) { + if (!app.isPackaged) { return } diff --git a/src/main/window/createMainWindow-close-confirmation.test.ts b/src/main/window/createMainWindow-close-confirmation.test.ts index 6f91dd4add8..d073f42a2fe 100644 --- a/src/main/window/createMainWindow-close-confirmation.test.ts +++ b/src/main/window/createMainWindow-close-confirmation.test.ts @@ -3,9 +3,6 @@ import { beforeEach, describe, expect, it, vi } from 'vitest' vi.mock('electron', async () => (await import('./createMainWindow-test-harness')).electronModuleMock() ) -vi.mock('@electron-toolkit/utils', async () => - (await import('./createMainWindow-test-harness')).electronToolkitUtilsMock() -) vi.mock('./macos-tahoe-release', async () => (await import('./createMainWindow-test-harness')).macosTahoeReleaseMock() ) diff --git a/src/main/window/createMainWindow-low-commit-oom-recovery.test.ts b/src/main/window/createMainWindow-low-commit-oom-recovery.test.ts index 218f48c5606..79dd716ea85 100644 --- a/src/main/window/createMainWindow-low-commit-oom-recovery.test.ts +++ b/src/main/window/createMainWindow-low-commit-oom-recovery.test.ts @@ -3,9 +3,6 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' vi.mock('electron', async () => (await import('./createMainWindow-test-harness')).electronModuleMock() ) -vi.mock('@electron-toolkit/utils', async () => - (await import('./createMainWindow-test-harness')).electronToolkitUtilsMock() -) vi.mock('./macos-tahoe-release', async () => (await import('./createMainWindow-test-harness')).macosTahoeReleaseMock() ) diff --git a/src/main/window/createMainWindow-markdown-editor-focus.test.ts b/src/main/window/createMainWindow-markdown-editor-focus.test.ts index ef6fca229d3..62897b32b10 100644 --- a/src/main/window/createMainWindow-markdown-editor-focus.test.ts +++ b/src/main/window/createMainWindow-markdown-editor-focus.test.ts @@ -3,9 +3,6 @@ import { beforeEach, describe, expect, it, vi } from 'vitest' vi.mock('electron', async () => (await import('./createMainWindow-test-harness')).electronModuleMock() ) -vi.mock('@electron-toolkit/utils', async () => - (await import('./createMainWindow-test-harness')).electronToolkitUtilsMock() -) vi.mock('./macos-tahoe-release', async () => (await import('./createMainWindow-test-harness')).macosTahoeReleaseMock() ) diff --git a/src/main/window/createMainWindow-recovery-reload-watchdog.test.ts b/src/main/window/createMainWindow-recovery-reload-watchdog.test.ts index e551579a7ab..afb155001a1 100644 --- a/src/main/window/createMainWindow-recovery-reload-watchdog.test.ts +++ b/src/main/window/createMainWindow-recovery-reload-watchdog.test.ts @@ -12,9 +12,6 @@ vi.mock('../crash-reporting/durable-crash-breadcrumb', async (importOriginal) => vi.mock('electron', async () => (await import('./createMainWindow-test-harness')).electronModuleMock() ) -vi.mock('@electron-toolkit/utils', async () => - (await import('./createMainWindow-test-harness')).electronToolkitUtilsMock() -) vi.mock('./macos-tahoe-release', async () => (await import('./createMainWindow-test-harness')).macosTahoeReleaseMock() ) @@ -33,7 +30,7 @@ vi.mock('../browser/browser-client-page-renderer-runtime', async () => { import { createMainWindow } from './createMainWindow' import { browserWindowMock, - isMock, + appMock, powerMonitorOnMock, resetMainWindowMocks } from './createMainWindow-test-harness' @@ -404,7 +401,7 @@ describe('renderer recovery reload watchdog', () => { it('gives the dev server a longer budget than a packaged load', () => { const onRecoveryReloadOutcome = vi.fn() const { browserWindowInstance, consoleError, crashRenderer } = createHarness() - isMock.dev = true + appMock.isPackaged = false vi.stubEnv('ELECTRON_RENDERER_URL', 'http://localhost:5173/') try { diff --git a/src/main/window/createMainWindow-renderer-crash-recovery.test.ts b/src/main/window/createMainWindow-renderer-crash-recovery.test.ts index ff33142454f..ca16e2df32c 100644 --- a/src/main/window/createMainWindow-renderer-crash-recovery.test.ts +++ b/src/main/window/createMainWindow-renderer-crash-recovery.test.ts @@ -3,9 +3,6 @@ import { beforeEach, describe, expect, it, vi } from 'vitest' vi.mock('electron', async () => (await import('./createMainWindow-test-harness')).electronModuleMock() ) -vi.mock('@electron-toolkit/utils', async () => - (await import('./createMainWindow-test-harness')).electronToolkitUtilsMock() -) vi.mock('./macos-tahoe-release', async () => (await import('./createMainWindow-test-harness')).macosTahoeReleaseMock() ) diff --git a/src/main/window/createMainWindow-renderer-launch-failure.test.ts b/src/main/window/createMainWindow-renderer-launch-failure.test.ts index 7befc2fe588..904c9d3fbd1 100644 --- a/src/main/window/createMainWindow-renderer-launch-failure.test.ts +++ b/src/main/window/createMainWindow-renderer-launch-failure.test.ts @@ -3,9 +3,6 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' vi.mock('electron', async () => (await import('./createMainWindow-test-harness')).electronModuleMock() ) -vi.mock('@electron-toolkit/utils', async () => - (await import('./createMainWindow-test-harness')).electronToolkitUtilsMock() -) vi.mock('./macos-tahoe-release', async () => (await import('./createMainWindow-test-harness')).macosTahoeReleaseMock() ) diff --git a/src/main/window/createMainWindow-startup-reveal.test.ts b/src/main/window/createMainWindow-startup-reveal.test.ts index bd7eeadc6b2..0e19bbe0b8c 100644 --- a/src/main/window/createMainWindow-startup-reveal.test.ts +++ b/src/main/window/createMainWindow-startup-reveal.test.ts @@ -3,9 +3,6 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' vi.mock('electron', async () => (await import('./createMainWindow-test-harness')).electronModuleMock() ) -vi.mock('@electron-toolkit/utils', async () => - (await import('./createMainWindow-test-harness')).electronToolkitUtilsMock() -) vi.mock('./macos-tahoe-release', async () => (await import('./createMainWindow-test-harness')).macosTahoeReleaseMock() ) diff --git a/src/main/window/createMainWindow-system-resume-relay.test.ts b/src/main/window/createMainWindow-system-resume-relay.test.ts index 71bf0cd7381..342f41f59f2 100644 --- a/src/main/window/createMainWindow-system-resume-relay.test.ts +++ b/src/main/window/createMainWindow-system-resume-relay.test.ts @@ -3,9 +3,6 @@ import { beforeEach, describe, expect, it, vi } from 'vitest' vi.mock('electron', async () => (await import('./createMainWindow-test-harness')).electronModuleMock() ) -vi.mock('@electron-toolkit/utils', async () => - (await import('./createMainWindow-test-harness')).electronToolkitUtilsMock() -) vi.mock('./macos-tahoe-release', async () => (await import('./createMainWindow-test-harness')).macosTahoeReleaseMock() ) diff --git a/src/main/window/createMainWindow-terminal-focus-shortcuts.test.ts b/src/main/window/createMainWindow-terminal-focus-shortcuts.test.ts index 8287b9bcecb..b0c4c5519d1 100644 --- a/src/main/window/createMainWindow-terminal-focus-shortcuts.test.ts +++ b/src/main/window/createMainWindow-terminal-focus-shortcuts.test.ts @@ -3,9 +3,6 @@ import { beforeEach, describe, expect, it, vi } from 'vitest' vi.mock('electron', async () => (await import('./createMainWindow-test-harness')).electronModuleMock() ) -vi.mock('@electron-toolkit/utils', async () => - (await import('./createMainWindow-test-harness')).electronToolkitUtilsMock() -) vi.mock('./macos-tahoe-release', async () => (await import('./createMainWindow-test-harness')).macosTahoeReleaseMock() ) @@ -17,7 +14,7 @@ vi.mock('../browser/browser-manager', async () => import { createMainWindow } from './createMainWindow' import { ipcMain } from 'electron' import { resetExpectedTeardownStateForTest } from '../crash-reporting/expected-teardown-state' -import { browserWindowMock, isMock, resetMainWindowMocks } from './createMainWindow-test-harness' +import { browserWindowMock, appMock, resetMainWindowMocks } from './createMainWindow-test-harness' describe('createMainWindow', () => { beforeEach(() => { @@ -751,7 +748,7 @@ describe('createMainWindow', () => { }) it('toggles devtools on F12 in development', () => { - isMock.dev = true + appMock.isPackaged = false const windowHandlers: Record void> = {} const webContents = { diff --git a/src/main/window/createMainWindow-test-harness.ts b/src/main/window/createMainWindow-test-harness.ts index abf2dd8c829..4a650721d74 100644 --- a/src/main/window/createMainWindow-test-harness.ts +++ b/src/main/window/createMainWindow-test-harness.ts @@ -27,7 +27,11 @@ export const notificationMock: Mock<(...args: unknown[]) => { show: MainWindowSp export const powerMonitorOnMock: MainWindowSpy = vi.fn() export const powerMonitorRemoveListenerMock: MainWindowSpy = vi.fn() export const routePartitionAllowedMock: Mock<(partition: string) => boolean> = vi.fn(() => false) -export const isMock = { dev: false } +export const appMock: { isPackaged: boolean; on: MainWindowSpy; removeListener: MainWindowSpy } = { + isPackaged: true, + on: vi.fn(), + removeListener: vi.fn() +} export const macosTahoeMock = { value: false } type IpcMainMock = { @@ -45,7 +49,7 @@ const ipcMainMock: IpcMainMock = { } export type ElectronModuleMock = { - app: { on: MainWindowSpy; removeListener: MainWindowSpy } + app: typeof appMock BrowserWindow: typeof browserWindowMock ipcMain: IpcMainMock Menu: { buildFromTemplate: typeof buildFromTemplateMock } @@ -70,7 +74,7 @@ export type BrowserManagerModuleMock = { // re-declaring the shared electron surface. export function electronModuleMock(): ElectronModuleMock { return { - app: { on: vi.fn(), removeListener: vi.fn() }, + app: appMock, BrowserWindow: browserWindowMock, ipcMain: ipcMainMock, Menu: { buildFromTemplate: buildFromTemplateMock }, @@ -85,12 +89,6 @@ export function electronModuleMock(): ElectronModuleMock { } } -export function electronToolkitUtilsMock() { - return { - is: isMock - } -} - export function macosTahoeReleaseMock() { return { isMacosTahoeOrNewer: vi.fn(() => macosTahoeMock.value) @@ -129,7 +127,7 @@ export function resetMainWindowMocks(): void { powerMonitorRemoveListenerMock.mockReset() routePartitionAllowedMock.mockReset() routePartitionAllowedMock.mockReturnValue(false) - isMock.dev = false + appMock.isPackaged = true macosTahoeMock.value = false ipcMainMock.on.mockReset() ipcMainMock.removeListener.mockReset() diff --git a/src/main/window/createMainWindow-tray-minimize-close.test.ts b/src/main/window/createMainWindow-tray-minimize-close.test.ts index 417991f8a0d..1585fca3bfd 100644 --- a/src/main/window/createMainWindow-tray-minimize-close.test.ts +++ b/src/main/window/createMainWindow-tray-minimize-close.test.ts @@ -7,9 +7,6 @@ const { recordAgentSessionRuntimeEndMock } = vi.hoisted(() => ({ vi.mock('electron', async () => (await import('./createMainWindow-test-harness')).electronModuleMock() ) -vi.mock('@electron-toolkit/utils', async () => - (await import('./createMainWindow-test-harness')).electronToolkitUtilsMock() -) vi.mock('./macos-tahoe-release', async () => (await import('./createMainWindow-test-harness')).macosTahoeReleaseMock() ) diff --git a/src/main/window/createMainWindow-user-quit-close.test.ts b/src/main/window/createMainWindow-user-quit-close.test.ts index fe9aa5a2beb..89077b975ad 100644 --- a/src/main/window/createMainWindow-user-quit-close.test.ts +++ b/src/main/window/createMainWindow-user-quit-close.test.ts @@ -3,9 +3,6 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' vi.mock('electron', async () => (await import('./createMainWindow-test-harness')).electronModuleMock() ) -vi.mock('@electron-toolkit/utils', async () => - (await import('./createMainWindow-test-harness')).electronToolkitUtilsMock() -) vi.mock('./macos-tahoe-release', async () => (await import('./createMainWindow-test-harness')).macosTahoeReleaseMock() ) diff --git a/src/main/window/createMainWindow-zoom-and-tab-switch-shortcuts.test.ts b/src/main/window/createMainWindow-zoom-and-tab-switch-shortcuts.test.ts index c537504484d..7d9eaf28bed 100644 --- a/src/main/window/createMainWindow-zoom-and-tab-switch-shortcuts.test.ts +++ b/src/main/window/createMainWindow-zoom-and-tab-switch-shortcuts.test.ts @@ -3,9 +3,6 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' vi.mock('electron', async () => (await import('./createMainWindow-test-harness')).electronModuleMock() ) -vi.mock('@electron-toolkit/utils', async () => - (await import('./createMainWindow-test-harness')).electronToolkitUtilsMock() -) vi.mock('./macos-tahoe-release', async () => (await import('./createMainWindow-test-harness')).macosTahoeReleaseMock() ) diff --git a/src/main/window/createMainWindow.test.ts b/src/main/window/createMainWindow.test.ts index 79b9a742533..a3843ae5955 100644 --- a/src/main/window/createMainWindow.test.ts +++ b/src/main/window/createMainWindow.test.ts @@ -3,9 +3,6 @@ import { beforeEach, describe, expect, it, vi } from 'vitest' vi.mock('electron', async () => (await import('./createMainWindow-test-harness')).electronModuleMock() ) -vi.mock('@electron-toolkit/utils', async () => - (await import('./createMainWindow-test-harness')).electronToolkitUtilsMock() -) vi.mock('./macos-tahoe-release', async () => (await import('./createMainWindow-test-harness')).macosTahoeReleaseMock() ) diff --git a/src/main/window/createMainWindow.ts b/src/main/window/createMainWindow.ts index 201ef12e308..5ee10dbc80d 100644 --- a/src/main/window/createMainWindow.ts +++ b/src/main/window/createMainWindow.ts @@ -1,5 +1,4 @@ -import { BrowserWindow, nativeTheme, powerMonitor, screen } from 'electron' -import { is } from '@electron-toolkit/utils' +import { app, BrowserWindow, nativeTheme, powerMonitor, screen } from 'electron' import { join } from 'node:path' import { getAppIconPath } from '../app-icon' import { browserManager } from '../browser/browser-manager' @@ -39,7 +38,7 @@ export { WINDOW_QUIT_RENDERER_ACK_TIMEOUT_MS } export function loadMainWindow(mainWindow: BrowserWindow, observer?: MainWindowLoadObserver): void { const load = - is.dev && process.env.ELECTRON_RENDERER_URL + !app.isPackaged && process.env.ELECTRON_RENDERER_URL ? mainWindow.loadURL(process.env.ELECTRON_RENDERER_URL) : mainWindow.loadFile(join(__dirname, '../renderer/index.html')) // Observe each load promise so failures cannot leave recovery waiting silently. diff --git a/src/main/window/dashboard-popout-window.test.ts b/src/main/window/dashboard-popout-window.test.ts index 791133de126..2afb8b99fe8 100644 --- a/src/main/window/dashboard-popout-window.test.ts +++ b/src/main/window/dashboard-popout-window.test.ts @@ -11,7 +11,7 @@ const { getAllDisplaysMock, installNavigationPolicyMock, sendToTrustedUIRendererMock, - isMock + appMock } = vi.hoisted(() => { const created: FakeWindow[] = [] @@ -112,7 +112,7 @@ const { ]), installNavigationPolicyMock: vi.fn(), sendToTrustedUIRendererMock: vi.fn(), - isMock: { dev: false } as { dev: boolean } + appMock: { isPackaged: true } } }) @@ -122,13 +122,18 @@ const { instances vi.mock('electron', () => ({ - app: { on: appOnMock, removeListener: appRemoveListenerMock }, + app: { + on: appOnMock, + removeListener: appRemoveListenerMock, + get isPackaged() { + return appMock.isPackaged + } + }, BrowserWindow: BrowserWindowMock, nativeTheme: nativeThemeMock, screen: { getAllDisplays: getAllDisplaysMock } })) -vi.mock('@electron-toolkit/utils', () => ({ is: isMock })) vi.mock('../ipc/ui', () => ({ sendToTrustedUIRenderer: sendToTrustedUIRendererMock })) vi.mock('./privileged-window-navigation', () => ({ installPrivilegedWindowNavigationPolicy: installNavigationPolicyMock @@ -182,7 +187,7 @@ afterEach(() => vi.unstubAllEnvs()) describe('createOrFocusDashboardPopout', () => { beforeEach(() => { instances.length = 0 - isMock.dev = false + appMock.isPackaged = true vi.stubEnv('ELECTRON_RENDERER_URL', '') getAllDisplaysMock.mockReturnValue([{ workArea: { x: 0, y: 0, width: 1920, height: 1080 } }]) }) @@ -246,7 +251,7 @@ describe('createOrFocusDashboardPopout', () => { }) it('loads the dev server URL when in dev', () => { - isMock.dev = true + appMock.isPackaged = false vi.stubEnv('ELECTRON_RENDERER_URL', RENDERER_URL) createOrFocusDashboardPopout(makeStore() as never) const win = instances[0] diff --git a/src/main/window/dashboard-popout-window.ts b/src/main/window/dashboard-popout-window.ts index 15e4964a46f..1cead2c33e4 100644 --- a/src/main/window/dashboard-popout-window.ts +++ b/src/main/window/dashboard-popout-window.ts @@ -1,6 +1,5 @@ import { app, BrowserWindow, nativeTheme, type WebContents, type Event } from 'electron' import { join } from 'node:path' -import { is } from '@electron-toolkit/utils' import type { Store } from '../persistence' import { isBackgroundLaunch, showWindowWithoutStealingFocus } from './foreground-activation-policy' import { rectHasVisibleAreaOnAnyDisplay } from './window-bounds-validation' @@ -101,7 +100,7 @@ function broadcastPopoutOpenChanged(open: boolean): void { function loadDashboardPopout(window: BrowserWindow): void { // Why: mirror loadMainWindow's dev/prod branch — the dev server serves the // second HTML entry, prod loads the emitted file. - if (is.dev && process.env.ELECTRON_RENDERER_URL) { + if (!app.isPackaged && process.env.ELECTRON_RENDERER_URL) { void window.loadURL(`${process.env.ELECTRON_RENDERER_URL}/popout.html`) } else { void window.loadFile(join(__dirname, '../renderer/popout.html')) diff --git a/src/main/window/main-window-shortcut-routing.ts b/src/main/window/main-window-shortcut-routing.ts index ba2ecb35424..8fe59c4a5fd 100644 --- a/src/main/window/main-window-shortcut-routing.ts +++ b/src/main/window/main-window-shortcut-routing.ts @@ -1,5 +1,5 @@ +import { app } from 'electron' import type { BrowserWindow } from 'electron' -import { is } from '@electron-toolkit/utils' import { ModifierDoubleTapDetector, toModifierDoubleTapEvent @@ -116,7 +116,7 @@ export function installMainWindowShortcutRouting(args: { return } - if (input.type === 'keyDown' && is.dev && input.code === 'F12') { + if (input.type === 'keyDown' && !app.isPackaged && input.code === 'F12') { event.preventDefault() if (mainWindow.webContents.isDevToolsOpened()) { mainWindow.webContents.closeDevTools() diff --git a/src/main/window/renderer-recovery-reload-watchdog.test.ts b/src/main/window/renderer-recovery-reload-watchdog.test.ts index b6e854bbbf1..9148ab5a326 100644 --- a/src/main/window/renderer-recovery-reload-watchdog.test.ts +++ b/src/main/window/renderer-recovery-reload-watchdog.test.ts @@ -7,7 +7,7 @@ import { RENDERER_RECOVERY_LOAD_TIMEOUT_MS } from './renderer-recovery-reload-watchdog' -vi.mock('@electron-toolkit/utils', () => ({ is: { dev: false } })) +vi.mock('electron', () => ({ app: { isPackaged: true } })) function createHarness() { const webContents = Object.assign(new EventEmitter(), { id: 143 }) diff --git a/src/main/window/renderer-recovery-reload-watchdog.ts b/src/main/window/renderer-recovery-reload-watchdog.ts index 4d21da2a2cc..6ad767e0590 100644 --- a/src/main/window/renderer-recovery-reload-watchdog.ts +++ b/src/main/window/renderer-recovery-reload-watchdog.ts @@ -1,4 +1,4 @@ -import { is } from '@electron-toolkit/utils' +import { app } from 'electron' import type { BrowserWindow } from 'electron' import { isSystemSessionEnding } from '../crash-reporting/expected-teardown-state' import type { LowCommitOomVerdict } from '../crash-reporting/low-commit-oom-recovery-gate' @@ -108,7 +108,7 @@ export function createRendererRecoveryReloadWatchdog(args: { } // Match loadMainWindow's dev/prod branch. const timeoutMs = (): number => - is.dev && process.env.ELECTRON_RENDERER_URL + !app.isPackaged && process.env.ELECTRON_RENDERER_URL ? RENDERER_RECOVERY_DEV_LOAD_TIMEOUT_MS : RENDERER_RECOVERY_LOAD_TIMEOUT_MS diff --git a/src/main/window/workspace-space-window.ts b/src/main/window/workspace-space-window.ts index 7e1f1a5cc23..684f0fc08be 100644 --- a/src/main/window/workspace-space-window.ts +++ b/src/main/window/workspace-space-window.ts @@ -1,6 +1,5 @@ -import { BrowserWindow, nativeTheme, type WebContents } from 'electron' +import { app, BrowserWindow, nativeTheme, type WebContents } from 'electron' import { join } from 'node:path' -import { is } from '@electron-toolkit/utils' import { isBackgroundLaunch, showWindowWithoutStealingFocus } from './foreground-activation-policy' import { installPrivilegedWindowNavigationPolicy } from './privileged-window-navigation' import { sendToTrustedUIRenderer } from '../ipc/ui' @@ -85,7 +84,7 @@ export function createOrFocusWorkspaceSpaceWindow(store: Store): BrowserWindow { } }) - if (is.dev && process.env.ELECTRON_RENDERER_URL) { + if (!app.isPackaged && process.env.ELECTRON_RENDERER_URL) { void window.loadURL(`${process.env.ELECTRON_RENDERER_URL}/space.html`) } else { void window.loadFile(join(__dirname, '../renderer/space.html'))