test(ui): add AccountButton connected integration test#9191
test(ui): add AccountButton connected integration test#9191alexcarpenter wants to merge 11 commits into
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
1 Skipped Deployment
|
🦋 Changeset detectedLatest commit: 22e6748 The changes in this PR will be included in the next version bump. This PR includes changesets to release 0 packagesWhen changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository YAML (base), Repository UI (inherited) Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Comment |
ApprovabilityVerdict: Approved This PR adds integration tests for the AccountButton component with no production code changes. The empty changeset confirms no packages are affected, making this a low-risk test-only addition. You can customize Macroscope's approvability policy. Learn more. |
…n AccountButton integration test
Dismissing prior approval to re-evaluate 088fc5a
…ccountButton Gate add-account and sign-out-of-all on singleSessionMode in the controller, and render pending invitations/suggestions even with no organization memberships.
… suggestions - add afterSelectOrganizationUrl/afterSelectPersonalUrl props (mirroring OrganizationSwitcher) instead of the wrong afterCreateOrganizationUrl redirect - restore sign-out redirect URLs via buildAfterSignOutUrl / buildAfterMultiSessionSingleSignOutUrl - render accepted suggestions as a non-actionable 'Pending approval' label
Track the single in-flight action in the connected container: the clicked affordance shows a spinner while others disable to block double-submits, the popover closes only on success, and busy state clears on rejection so the UI never hangs. Add a Mosaic Spinner primitive and a skeleton trigger shown while the controller loads.
…mises The controller's setActive/signOut/navigate callbacks return promises but were declared () => void, tripping no-misused-promises. Declare the container-awaited actions as void | Promise<unknown> and void-wrap the fire-and-forget navigations; the view keeps its () => void contract.
… quick actions Add a useSpinDelay hook (a leaner rework of smeijer/spin-delay around a single visible flag) and gate the AccountButton popover spinner through it. Fast actions that resolve before the delay never flash a spinner, and any spinner shown is held for a minimum duration so it can't flicker. The container still guards re-entry on the immediate pendingKey; only the visual feedback is delayed.
Split the 1032-line account-button.view.tsx into focused modules: the slot recipe (+ registry augmentation) moves to account-button.recipe.ts and the data-contract types + accountBusyKeys to account-button.types.ts, leaving the view at ~600 lines of pure components. Generalize useSpinDelay from a boolean to a nullable value (T | null) so it carries the last non-null value through the minDuration hold itself. The container drops its during-render ref and derives the delayed pending key in one line. No behavior change.
- Rename the view's props type to AccountButtonViewProps so AccountButtonProps is no longer exported with two different meanings across sibling files - Drop the dead status field from AccountButtonData; the view only ever renders ready data, and the controller/container handshake keeps its own discriminant - Extract a single BusyButton primitive to replace four hand-wired busy buttons (inline join/accept, hover sign-out, header actions, footer sign-out-all), removing the duplicated disabled/spinner idiom No behavior change; 38 account-button tests pass, tsc and eslint clean.
Route the controller through useOrganizationListInView so memberships, suggestions, and invitations page in on scroll instead of showing only the first page. Expose an opaque loadMoreRef plus hasMoreRows/isFetchingRows on the ready contract; the view renders a bounded scroll container with a sentinel and end-of-list spinner. Accounts are unaffected (not paginated). 41 account-button tests pass; tsc and eslint clean.
The swingset AccountButton story imported the removed AccountButtonProps type and passed status='ready', both of which broke after the view API changed (AccountButtonViewProps; status now lives on the controller, not the presentational view). Update the story to match.
Stacked on #9185. Adds busy/loading UX to the connected AccountButton + an end-to-end integration test.
Changes
Busy/loading states (
controller+container)pendingKey. Clicked affordance spins, others disable (blocks double-submit). Popover closes only on success; busy clears on rejection so UI never hangs.void | Promise<unknown>to satisfyno-misused-promises; fire-and-forget navigations void-wrapped.Spin-delay (
useSpinDelayhook + tests)T | nullflag. Fast actions resolve before delay → no spinner flash; any spinner shown held for min duration → no flicker. Re-entry still guarded on immediatependingKey; only visuals delayed.View decomposition (1032 → ~600 lines)
account-button.recipe.ts, data-contract types +accountBusyKeys→account-button.types.ts.BusyButtonprimitive replaces 4 hand-wired busy buttons (inline join/accept, hover sign-out, header actions, footer sign-out-all).AccountButtonViewProps; deadstatusfield dropped. No behavior change.Spinner Mosaic primitive.
Integration test (14 tests)
Renders real view through real controller against mocked
@clerk/shared/react, drives real popover + rows/actions, asserts Clerk calls + close-on-success.setActive(...)+ closesetActive({session})+ closesignOut(...)+ closeaccept()+revalidate()+ closenavigate(...), popover stays openCovers every
closeOnSuccesscallback + every navigation through real DOM.Not re-tested here (owned elsewhere): a11y/focus-trap (popover primitive suite), data derivation/gating (
controller.test.tsx). Per-row sign-out is hover-revealed (pointer-events:none), so that one usesfireEvent.click(noted inline).Parity gaps (tracked separately, not test gaps): no
hidePersonal, force-org-selection, or trigger pending-counter badge yet.Changeset
Empty — feature ships under #9184 / #9185, no user-facing change here.