import json import re from pathlib import Path ROOT = Path(__file__).resolve().parents[2] def _read(path: str) -> str: return (ROOT / path).read_text(encoding="utf-8") def _section(source: str, start: str, end: str) -> str: start_index = source.index(start) end_index = source.index(end, start_index) return source[start_index:end_index] def test_desktop_resume_is_visible_first_and_single_flight() -> None: main_ts = _read("desktop/electron/src/main.ts") resume = _section( main_ts, "async function openOrResumeDesktopApp", "function stopGateway", ) assert "let gatewayStartPromise: Promise | null = null" in main_ts assert "startupInProgress" not in main_ts assert "function ensureGatewayStarted(): Promise" in main_ts assert "gatewayStartPromise = startGatewayWithPortRecovery().finally" in main_ts assert "gatewayStartPromise = null" in main_ts assert ( "function isCurrentWindowAtControlUi(window: BrowserWindow, gatewayUrl: string): boolean" in main_ts ) assert resume.index("await createMainWindow()") < resume.index("ensureGatewayStarted()") assert "focusMainWindow()" in resume assert "reuseHealthyGatewayState()" in resume assert "loadControlUiIntoCurrentWindow(gateway.url)" in resume def test_desktop_gateway_completion_uses_current_live_window() -> None: main_ts = _read("desktop/electron/src/main.ts") load_current = _section( main_ts, "async function loadControlUiIntoCurrentWindow", "async function openOrResumeDesktopApp", ) assert "function currentMainWindow(): BrowserWindow | null" in main_ts assert "const window = currentMainWindow()" in load_current assert "if (!window) return" in load_current assert "if (window.isDestroyed()) return" in load_current assert "isCurrentWindowAtControlUi(window, gatewayUrl)" in load_current guard_index = load_current.index("isCurrentWindowAtControlUi(window, gatewayUrl)") load_index = load_current.index("await loadControlUi(window, gatewayUrl)") assert guard_index < load_index assert "current.pathname === '/control'" in main_ts assert "current.pathname.startsWith('/control/')" in main_ts assert "if (mainWindow === window) mainWindow = null" in main_ts def test_desktop_activation_retry_and_second_instance_share_resume_helper() -> None: main_ts = _read("desktop/electron/src/main.ts") retry = _section( main_ts, "ipcMain.handle('desktop:boot:retry'", "ipcMain.handle('desktop:boot:quit'", ) assert "if (process.platform !== 'darwin') app.quit()" in main_ts assert "app.on('activate', () => {\n void openOrResumeDesktopApp()" in main_ts # second-instance resumes the app via the shared helper (a diagnostic log # line precedes the resume call — see the #446 relaunch-retry contract). second_instance = _section( main_ts, "app.on('second-instance', () => {", "void app.whenReady().then", ) assert "void openOrResumeDesktopApp()" in second_instance assert "void app.whenReady().then" in main_ts assert "void openOrResumeDesktopApp()" in _section( main_ts, "void app.whenReady().then", "})\n}", ) # Retry backs both the boot-error button and the Control UI "Restart runtime" # action, so it forces a real restart: an in-flight start is joined (clearing # the stale error), otherwise an owned gateway is torn down and awaited before # respawn rather than reused, so a healthy-but-misbehaving runtime can restart. assert "if (gatewayStartPromise)" in retry assert "stopGateway()" in retry assert "await waitForGatewayProcessExit(previousChild)" in retry assert "clearReusableGatewayState()" in retry assert "void openOrResumeDesktopApp()" in retry def test_boot_error_panel_exposes_reset_setup_recovery() -> None: boot_html = _read("desktop/electron/src/boot.html") reset_flow = _section( boot_html, "async function resetSetup()", "setInterval", ) assert 'id="resetSetup"' in boot_html assert "Reset setup" in boot_html assert 'data-i18n="resetSetup"' in boot_html assert "function resetSetup()" in boot_html assert "api.resetDesktopSettings" in boot_html assert "window.confirm(" in boot_html assert "msg.resetConfirm" in boot_html assert "msg.resetPhase" in boot_html assert "msg.resetProgress" in boot_html assert "msg.resetFailed" in boot_html assert "workspace path, identity, memory, and chat history are kept" in boot_html assert "await api.resetDesktopSettings()" in reset_flow assert "await api.retryStartup()" in reset_flow assert reset_flow.index("await api.resetDesktopSettings()") < reset_flow.index( "await api.retryStartup()" ) assert "errorPanel.classList.add('visible')" in reset_flow def test_recovery_ui_is_accessible_and_runtime_reachable() -> None: boot_html = _read("desktop/electron/src/boot.html") assert '
' in boot_html assert '