Skip to content

feat(debugger): mock updater - #1478

Merged
zhangmo8 merged 2 commits into
devfrom
debug-upgrade
Apr 16, 2026
Merged

feat(debugger): mock updater#1478
zhangmo8 merged 2 commits into
devfrom
debug-upgrade

Conversation

@zhangmo8

@zhangmo8 zhangmo8 commented Apr 16, 2026

Copy link
Copy Markdown
Collaborator

Summary by CodeRabbit

  • New Features

    • Add mock update simulation with controls in Settings and buttons to trigger/clear a mocked downloaded update.
    • UI text added for mock update controls in multiple locales.
  • Tests

    • Add unit tests covering mock update flows, relaunch/exit behavior, and store/presenter interactions.

@coderabbitai

coderabbitai Bot commented Apr 16, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

Adds 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

Cohort / File(s) Summary
Presenter Core Logic
src/main/presenter/upgradePresenter/index.ts
Added isMock?: boolean to VersionInfo, introduced _isMockUpdate, refactored quit/install into beginInstallFlow(), added mockDownloadedUpdate() and clearMockUpdate(), and added _doMockQuitAndInstall() with mock relaunch/exit flow.
Renderer UI
src/renderer/settings/components/AboutUsSettings.vue
Added DEV-only mock update buttons and handlers that call store actions and show error toasts when needed.
Renderer Store & Types
src/renderer/src/stores/upgrade.ts, src/shared/types/presenters/legacy.presenters.d.ts
Propagated isMock?: boolean into UpdateInfo, added isMockUpdate computed flag, and new actions mockDownloadedUpdate() / clearMockUpdate(); updated IUpgradePresenter declarations.
Internationalization
src/renderer/src/i18n/*/about.json (12 files)
Added mockUpdateButton and clearMockUpdateButton translation keys across supported locales.
Tests
test/main/presenter/upgradePresenter.test.ts, test/renderer/components/AboutUsSettings.test.ts, test/renderer/stores/upgradeStore.test.ts
Extended mocks for app.relaunch/app.exit, added tests for mock-download and mock-restart flows, and updated UI/store tests to include mock button behavior.

Sequence Diagram

sequenceDiagram
    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
Loading

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly Related PRs

Suggested Reviewers

  • zerob13

Poem

🐇 I nudged a mock update, soft and neat,
Buttons for devs, a tiny testing treat.
A relaunch hop, then a quiet exit beat,
No real installs—just rehearsal sweet. ✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(debugger): mock updater' accurately describes the main changes—adding mock update functionality for debugging purposes across the presenter, UI, store, and test files.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch debug-upgrade

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
test/main/presenter/upgradePresenter.test.ts (1)

92-101: Reset new app lifecycle mocks in beforeEach for stronger test isolation.

appRelaunchMock and appExitMock are 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 wrapping installAction() invocation for error safety.

The installAction callback executes inside a setTimeout, so any exception it throws won't be caught by the outer try-catch. While the current callbacks (autoUpdater.quitAndInstall and app.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

📥 Commits

Reviewing files that changed from the base of the PR and between bc1ea51 and f39bd82.

📒 Files selected for processing (19)
  • src/main/presenter/upgradePresenter/index.ts
  • src/renderer/settings/components/AboutUsSettings.vue
  • src/renderer/src/i18n/da-DK/about.json
  • src/renderer/src/i18n/en-US/about.json
  • src/renderer/src/i18n/fa-IR/about.json
  • src/renderer/src/i18n/fr-FR/about.json
  • src/renderer/src/i18n/he-IL/about.json
  • src/renderer/src/i18n/ja-JP/about.json
  • src/renderer/src/i18n/ko-KR/about.json
  • src/renderer/src/i18n/pt-BR/about.json
  • src/renderer/src/i18n/ru-RU/about.json
  • src/renderer/src/i18n/zh-CN/about.json
  • src/renderer/src/i18n/zh-HK/about.json
  • src/renderer/src/i18n/zh-TW/about.json
  • src/renderer/src/stores/upgrade.ts
  • src/shared/types/presenters/legacy.presenters.d.ts
  • test/main/presenter/upgradePresenter.test.ts
  • test/renderer/components/AboutUsSettings.test.ts
  • test/renderer/stores/upgradeStore.test.ts

Comment thread src/renderer/settings/components/AboutUsSettings.vue Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 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

📥 Commits

Reviewing files that changed from the base of the PR and between f39bd82 and cc0f6a4.

📒 Files selected for processing (1)
  • src/renderer/settings/components/AboutUsSettings.vue

@zhangmo8
zhangmo8 merged commit 06c9ddb into dev Apr 16, 2026
3 checks passed
@zhangmo8
zhangmo8 deleted the debug-upgrade branch April 16, 2026 03:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant