feat(debugger): mock updater - #1478
Conversation
📝 WalkthroughWalkthroughAdds a mock-update flow and controls: presenter can mark/clear a mock downloaded update and run a mock restart path; quit-and-install orchestration was refactored into a shared helper; renderer UI, store, types, i18n, and tests were updated to expose and exercise mock-update behavior. Changes
Sequence DiagramsequenceDiagram
participant User as User (Dev)
participant UI as AboutUsSettings
participant Store as Upgrade Store
participant Presenter as UpgradePresenter
participant App as Electron App
User->>UI: Click "Mock Downloaded Update"
UI->>Store: mockDownloadedUpdate()
Store->>Presenter: mockDownloadedUpdate()
Presenter->>Presenter: set _isMockUpdate = true\nemit STATUS_CHANGED
Presenter-->>Store: return true
Store->>Store: syncFromPresenterStatus()
Store-->>UI: isMockUpdate = true
User->>UI: Click "Restart/Install"
UI->>Store: restartToUpdate()
Store->>Presenter: restartToUpdate()
Presenter->>Presenter: check _isMockUpdate
alt Mock Path
Presenter->>Presenter: _doMockQuitAndInstall()\nbeginInstallFlow()
Presenter->>App: setTimeout 500ms -> app.relaunch()
Presenter->>App: app.exit()
else Real Path
Presenter->>App: autoUpdater.quitAndInstall()
end
Estimated Code Review Effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly Related PRs
Suggested Reviewers
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
test/main/presenter/upgradePresenter.test.ts (1)
92-101: Reset new app lifecycle mocks inbeforeEachfor stronger test isolation.
appRelaunchMockandappExitMockare newly introduced but not reset here.♻️ Suggested test-isolation patch
setApplicationQuittingMock.mockReset() appQuitMock.mockReset() + appRelaunchMock.mockReset() + appExitMock.mockReset()🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@test/main/presenter/upgradePresenter.test.ts` around lines 92 - 101, The beforeEach in upgradePresenter.test.ts fails to reset the newly added lifecycle mocks, so add appRelaunchMock.mockReset() and appExitMock.mockReset() to the existing beforeEach block that currently calls vi.useFakeTimers(), autoUpdaterState.reset(), sendToMainMock.mockReset(), sendToRendererMock.mockReset(), floatingButtonDestroyMock.mockReset(), destroyFloatingChatWindowMock.mockReset(), setApplicationQuittingMock.mockReset(), and appQuitMock.mockReset(); update that beforeEach so appRelaunchMock and appExitMock are reset to ensure test isolation for the app relaunch/exit flows.src/main/presenter/upgradePresenter/index.ts (1)
436-464: Consider wrappinginstallAction()invocation for error safety.The
installActioncallback executes inside asetTimeout, so any exception it throws won't be caught by the outer try-catch. While the current callbacks (autoUpdater.quitAndInstallandapp.relaunch/exit) are unlikely to throw synchronously, wrapping the invocation would make the error handling more robust.🛡️ Optional: Add error handling around installAction
setTimeout(() => { - installAction() + try { + installAction() + } catch (e) { + console.error('Install action failed', e) + this.setUpdatingFlag(false) + eventBus.sendToMain(WINDOW_EVENTS.SET_APPLICATION_QUITTING, { isQuitting: false }) + eventBus.sendToRenderer(UPDATE_EVENTS.ERROR, SendTarget.ALL_WINDOWS, { + error: e instanceof Error ? e.message : String(e) + }) + } }, 500)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/presenter/upgradePresenter/index.ts` around lines 436 - 464, beginInstallFlow currently calls installAction() inside a setTimeout so any exception escapes the outer try-catch; wrap the installAction invocation in a local try-catch inside that setTimeout (the one that calls installAction) to catch synchronous errors from installAction, log the error, call this.setUpdatingFlag(false), send WINDOW_EVENTS.SET_APPLICATION_QUITTING with { isQuitting: false } via eventBus.sendToMain, and send UPDATE_EVENTS.ERROR to all renderers via eventBus.sendToRenderer with the error message (mirroring the existing outer-catch cleanup); keep the existing 30s force-quit timeout and other calls such as this.prepareFloatingUiForUpdateInstall and eventBus.sendToRenderer(UPDATE_EVENTS.WILL_RESTART) unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/renderer/settings/components/AboutUsSettings.vue`:
- Around line 252-254: The expression defining showMockUpdateControls is
misformatted and failing oxfmt; fix the formatting of the computed initializer
(symbol: showMockUpdateControls and computed()) so it matches the project's
formatter style—i.e., place the arrow function and import.meta.env.DEV on the
same line and remove extraneous line breaks/spacing—and re-run oxfmt (or run
oxfmt --write) to ensure the file passes oxFmt checks before committing.
---
Nitpick comments:
In `@src/main/presenter/upgradePresenter/index.ts`:
- Around line 436-464: beginInstallFlow currently calls installAction() inside a
setTimeout so any exception escapes the outer try-catch; wrap the installAction
invocation in a local try-catch inside that setTimeout (the one that calls
installAction) to catch synchronous errors from installAction, log the error,
call this.setUpdatingFlag(false), send WINDOW_EVENTS.SET_APPLICATION_QUITTING
with { isQuitting: false } via eventBus.sendToMain, and send UPDATE_EVENTS.ERROR
to all renderers via eventBus.sendToRenderer with the error message (mirroring
the existing outer-catch cleanup); keep the existing 30s force-quit timeout and
other calls such as this.prepareFloatingUiForUpdateInstall and
eventBus.sendToRenderer(UPDATE_EVENTS.WILL_RESTART) unchanged.
In `@test/main/presenter/upgradePresenter.test.ts`:
- Around line 92-101: The beforeEach in upgradePresenter.test.ts fails to reset
the newly added lifecycle mocks, so add appRelaunchMock.mockReset() and
appExitMock.mockReset() to the existing beforeEach block that currently calls
vi.useFakeTimers(), autoUpdaterState.reset(), sendToMainMock.mockReset(),
sendToRendererMock.mockReset(), floatingButtonDestroyMock.mockReset(),
destroyFloatingChatWindowMock.mockReset(),
setApplicationQuittingMock.mockReset(), and appQuitMock.mockReset(); update that
beforeEach so appRelaunchMock and appExitMock are reset to ensure test isolation
for the app relaunch/exit flows.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 0833f0a8-2396-47ce-a01e-236bbbcf7340
📒 Files selected for processing (19)
src/main/presenter/upgradePresenter/index.tssrc/renderer/settings/components/AboutUsSettings.vuesrc/renderer/src/i18n/da-DK/about.jsonsrc/renderer/src/i18n/en-US/about.jsonsrc/renderer/src/i18n/fa-IR/about.jsonsrc/renderer/src/i18n/fr-FR/about.jsonsrc/renderer/src/i18n/he-IL/about.jsonsrc/renderer/src/i18n/ja-JP/about.jsonsrc/renderer/src/i18n/ko-KR/about.jsonsrc/renderer/src/i18n/pt-BR/about.jsonsrc/renderer/src/i18n/ru-RU/about.jsonsrc/renderer/src/i18n/zh-CN/about.jsonsrc/renderer/src/i18n/zh-HK/about.jsonsrc/renderer/src/i18n/zh-TW/about.jsonsrc/renderer/src/stores/upgrade.tssrc/shared/types/presenters/legacy.presenters.d.tstest/main/presenter/upgradePresenter.test.tstest/renderer/components/AboutUsSettings.test.tstest/renderer/stores/upgradeStore.test.ts
There was a problem hiding this comment.
🧹 Nitpick comments (1)
src/renderer/settings/components/AboutUsSettings.vue (1)
309-321: Extract shared mock-action error handling to avoid drift.Both handlers duplicate the same status/error-toast branch; consider a shared helper.
♻️ Minimal refactor
+const runMockAction = async (action: () => Promise<string>) => { + const status = await action() + if (status === 'error' && upgrade.updateError) { + showUpdateErrorToast(upgrade.updateError) + } +} + const handleMockDownloadedUpdate = async () => { - const status = await upgrade.mockDownloadedUpdate() - if (status === 'error' && upgrade.updateError) { - showUpdateErrorToast(upgrade.updateError) - } + await runMockAction(upgrade.mockDownloadedUpdate) } const handleClearMockUpdate = async () => { - const status = await upgrade.clearMockUpdate() - if (status === 'error' && upgrade.updateError) { - showUpdateErrorToast(upgrade.updateError) - } + await runMockAction(upgrade.clearMockUpdate) }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/renderer/settings/components/AboutUsSettings.vue` around lines 309 - 321, Both handlers handleMockDownloadedUpdate and handleClearMockUpdate duplicate identical status/error-toast logic; extract a shared helper (e.g., handleMockAction) that accepts the async action (upgrade.mockDownloadedUpdate or upgrade.clearMockUpdate), awaits it, and calls showUpdateErrorToast(upgrade.updateError) when status === 'error' && upgrade.updateError; then replace both functions to call that helper to avoid drift and centralize error handling.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@src/renderer/settings/components/AboutUsSettings.vue`:
- Around line 309-321: Both handlers handleMockDownloadedUpdate and
handleClearMockUpdate duplicate identical status/error-toast logic; extract a
shared helper (e.g., handleMockAction) that accepts the async action
(upgrade.mockDownloadedUpdate or upgrade.clearMockUpdate), awaits it, and calls
showUpdateErrorToast(upgrade.updateError) when status === 'error' &&
upgrade.updateError; then replace both functions to call that helper to avoid
drift and centralize error handling.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 4418b8db-8e1e-44cf-a535-342e5bb1795c
📒 Files selected for processing (1)
src/renderer/settings/components/AboutUsSettings.vue
Summary by CodeRabbit
New Features
Tests