Skip to content

fix(onboarding): prevent Apply Result dialog from being dismissed#1971

Merged
elibosley merged 1 commit intomainfrom
worktree-onboarding-modal-fix
Mar 27, 2026
Merged

fix(onboarding): prevent Apply Result dialog from being dismissed#1971
elibosley merged 1 commit intomainfrom
worktree-onboarding-modal-fix

Conversation

@Ajit-Mehrotra
Copy link
Copy Markdown
Contributor

@Ajit-Mehrotra Ajit-Mehrotra commented Mar 27, 2026

Summary

  • After pressing "Confirm and Apply" in the onboarding wizard, the Apply Result dialog (showing success/warning/error/timeout) could be dismissed via ESC key, clicking outside the overlay, or clicking the header close (X) button
  • This allowed users to bypass the result acknowledgment, miss important error/warning diagnostic information, and skip the intended navigation to the Next Steps page
  • The dialog is now non-dismissible — the only way to proceed is by clicking the OK button

What changed

OnboardingSummaryStep.vue — Apply Result UModal (line 1387):

  • Added :dismissible="false" — uses Nuxt UI's built-in mechanism to call e.preventDefault() on reka-ui's pointerDownOutside, interactOutside, and escapeKeyDown events
  • Added :close="false" — removes the header close (X) button, which would otherwise bypass the dismissible guard via reka-ui's DialogClose component
  • Removed the @update:open handler — dead code since no external close events can fire with both props set

OnboardingSummaryStep.test.ts:

  • Extended UModal stub to accept dismissible and close props and render them as data attributes
  • Added test verifying handleApplyResultConfirm() (triggered by OK button) is the sole path to close the dialog and advance to Next Steps

Modal state audit

"Confirm and Apply" clicked
     │
     ├─[has internal boot]──→ Boot Drive Warning Dialog (stays dismissible)
     │                          ↓ Continue
     │
     ├──→ handleComplete() runs
     │         │
     │    ★ Apply Result Dialog ← THIS IS FIXED
     │         Was: dismissible via ESC / click-outside / X button
     │         Now: only closable via OK button
     │         ↓ OK → goToNextStep() → NEXT_STEPS
     │
     └──→ InternalBootConfirmDialog (stays dismissible)

Scope decisions

Only the Apply Result Dialog was made non-dismissible. The Boot Drive Warning and InternalBootConfirmDialog retain their current dismissible behavior — these are pre-action confirmations where canceling/escaping is a valid user choice. The Apply Result Dialog is post-action; the settings have already been applied, and the user must acknowledge the outcome.

Test plan

  • Existing tests pass (635 passed, 6 skipped)
  • Manual: Navigate to Summary → Confirm and Apply → Apply Result appears
  • Manual: Press ESC → dialog stays open
  • Manual: Click outside overlay → dialog stays open
  • Manual: Verify no X button in header
  • Manual: Click OK → navigates to Next Steps
  • Manual: Verify all result severities (success, warning, error, timeout) are non-dismissible

Summary by CodeRabbit

  • Bug Fixes

    • Apply result dialog no longer allows users to accidentally dismiss it by clicking outside or using a close button. Users must now explicitly confirm the result to close the dialog and proceed.
  • Tests

    • Added test coverage for apply result dialog behavior, validating visibility states and confirmation flow mechanics.

- The Apply Result dialog (success/warning/error/timeout) that appears
  after "Confirm and Apply" could previously be closed by pressing ESC,
  clicking outside the overlay, or clicking the header close (X) button
- This allowed users to bypass the result acknowledgment and miss
  important error/warning information or skip navigation to Next Steps
- Add `:dismissible="false"` to block ESC, click-outside, and
  focus-outside close events (Nuxt UI built-in via reka-ui)
- Add `:close="false"` to remove the header close (X) button, which
  would otherwise bypass the dismissible guard via reka-ui's DialogClose
- Remove the now-dead `@update:open` handler since no external close
  events can fire
- The only way to close the dialog is now the OK button, which calls
  `handleApplyResultConfirm()` and advances to the Next Steps page
- Add test verifying OK is the sole close path for the result dialog
@codecov
Copy link
Copy Markdown

codecov bot commented Mar 27, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 52.09%. Comparing base (29f814b) to head (d7fe50b).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #1971   +/-   ##
=======================================
  Coverage   52.09%   52.09%           
=======================================
  Files        1031     1031           
  Lines       71573    71574    +1     
  Branches     8093     8092    -1     
=======================================
+ Hits        37284    37285    +1     
  Misses      34164    34164           
  Partials      125      125           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions
Copy link
Copy Markdown
Contributor

This plugin has been deployed to Cloudflare R2 and is available for testing.
Download it at this URL:

https://preview.dl.unraid.net/unraid-api/tag/PR1971/dynamix.unraid.net.plg

@Ajit-Mehrotra Ajit-Mehrotra marked this pull request as ready for review March 27, 2026 16:56
@Ajit-Mehrotra Ajit-Mehrotra self-assigned this Mar 27, 2026
@Ajit-Mehrotra Ajit-Mehrotra requested a review from elibosley March 27, 2026 16:56
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 27, 2026

Walkthrough

Changes prevent user-initiated dismissal of the apply-result dialog by setting dismissible and close to false, requiring explicit confirmation via handleApplyResultConfirm(). Test coverage added to verify this behavior with the extended modal stub.

Changes

Cohort / File(s) Summary
Test Suite Extensions
web/__test__/components/Onboarding/OnboardingSummaryStep.test.ts
Extended UModal test stub to handle dismissible and close props; added test case verifying apply-result dialog visibility and that onComplete is only called after explicit confirmation via handleApplyResultConfirm().
Component Behavior
web/src/components/Onboarding/steps/OnboardingSummaryStep.vue
Modified UModal for showApplyResultDialog to set :dismissible="false" and :close="false"; removed @update:open event handler to ensure dialog can only be closed through explicit confirmation.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 A dialog stands firm, no dismiss at the door,
Confirm the result—that's what we adore!
Tests ensure truth: no escape, no sneaky way,
Just handleApplyResultConfirm() saves the day! ✨

🚥 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 'fix(onboarding): prevent Apply Result dialog from being dismissed' is directly related to and clearly summarizes the main change: preventing dismissal of the Apply Result dialog by setting dismissible=false and close=false.
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 docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch worktree-onboarding-modal-fix

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.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
web/__test__/components/Onboarding/OnboardingSummaryStep.test.ts (1)

587-599: Test verifies the expected behavior; consider adding an assertion for the modal props.

The test correctly verifies that handleApplyResultConfirm() closes the dialog and invokes onComplete. To more explicitly verify the modal is configured as non-dismissible, consider asserting on the rendered attributes:

♻️ Optional enhancement to verify modal configuration
   it('only allows closing the apply result dialog via the OK button', async () => {
     const { wrapper, onComplete } = mountComponent();

     await clickApply(wrapper);

     const vm = getSummaryVm(wrapper);
     expect(vm.showApplyResultDialog).toBe(true);
     expect(onComplete).not.toHaveBeenCalled();

+    // Verify modal is configured as non-dismissible
+    const dialog = wrapper.find('[data-testid="dialog"]');
+    expect(dialog.attributes('data-dismissible')).toBe('false');
+    expect(dialog.attributes('data-close')).toBe('false');
+
     vm.handleApplyResultConfirm();
     expect(vm.showApplyResultDialog).toBe(false);
     expect(onComplete).toHaveBeenCalledOnce();
   });

As per coding guidelines: "Check for expected prop handling and event emissions in Vue components."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/__test__/components/Onboarding/OnboardingSummaryStep.test.ts` around
lines 587 - 599, Add an assertion that the rendered apply-result modal is
configured as non-dismissible: after clickApply(wrapper) and before calling
vm.handleApplyResultConfirm(), locate the rendered modal via the test wrapper
(e.g., wrapper.findComponent(...) or wrapper.find(selector)), and assert its
props such as persistent / noCloseOnBackdrop / closeOnEsc (or the equivalent
props used by the modal in OnboardingSummaryStep) are set to prevent dismissal;
keep existing checks of vm.showApplyResultDialog and onComplete. Use the
existing helpers (mountComponent, getSummaryVm, clickApply) to find the modal
and assert the modal props before confirming.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@web/__test__/components/Onboarding/OnboardingSummaryStep.test.ts`:
- Around line 587-599: Add an assertion that the rendered apply-result modal is
configured as non-dismissible: after clickApply(wrapper) and before calling
vm.handleApplyResultConfirm(), locate the rendered modal via the test wrapper
(e.g., wrapper.findComponent(...) or wrapper.find(selector)), and assert its
props such as persistent / noCloseOnBackdrop / closeOnEsc (or the equivalent
props used by the modal in OnboardingSummaryStep) are set to prevent dismissal;
keep existing checks of vm.showApplyResultDialog and onComplete. Use the
existing helpers (mountComponent, getSummaryVm, clickApply) to find the modal
and assert the modal props before confirming.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 7341f0a0-cd1f-4b7a-8927-15171a8e3f81

📥 Commits

Reviewing files that changed from the base of the PR and between 29f814b and d7fe50b.

📒 Files selected for processing (2)
  • web/__test__/components/Onboarding/OnboardingSummaryStep.test.ts
  • web/src/components/Onboarding/steps/OnboardingSummaryStep.vue

@elibosley elibosley merged commit 0db1410 into main Mar 27, 2026
13 checks passed
@elibosley elibosley deleted the worktree-onboarding-modal-fix branch March 27, 2026 17:02
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.

2 participants