fix(amicus): silent fallback for AmicusFab ErrorBoundary + provider-tree smoke test#1558
Merged
Merged
Conversation
…ree smoke test Follow-up polish to #1557. The architectural move (AmicusFab inside NavigationContainer) and the defensive try/catch in AmicusFab.tsx both landed in #1557. This PR adds two pieces that were outlined in the original plan but deferred: - Silent fallback for the ErrorBoundary that wraps <AmicusFab />. The default ErrorBoundary fallback is a full-screen "Something went wrong" view with a Retry button (flex:1), which would displace real UI if the FAB ever errored during render. A FAB failure should be invisible to the user — telemetry still captures it via logger.error in componentDidCatch. This is done by: 1. Extending ErrorBoundary Props with an optional `renderFallback` render-prop. When provided, it is used INSTEAD of the default centered fallback. Default behavior and existing call sites unchanged. 2. Adding AmicusFabErrorFallback, a component that renders null. 3. Wiring it into AppShell's AmicusFab boundary via `renderFallback`. - Provider-tree smoke test: mounts <App /> with the real @react-navigation/native (not the non-throwing jest.setup.js stub), waits for dbStatus -> 'ready', and asserts the full tree composes without throwing. This is the test that would have caught #1557's root cause before it reached TestFlight. Dependencies that are heavy, native-bound, or outside the provider-composition surface (RootNavigator, stores, DB init path, Sentry) are mocked; the NavigationContainer composition itself runs for real.
Test Results✅ All tests passed
Coverage
⏱️ Duration: 86.3s |
This was referenced Apr 21, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Follow-up polish to #1557. The architectural move (
<AmicusFab />inside<NavigationContainer>) and the defensive try/catch inAmicusFab.tsxboth landed in #1557. This PR adds two pieces that were outlined in the original plan but deferred:1. Silent fallback for the AmicusFab ErrorBoundary
The default
ErrorBoundaryfallback is aflex: 1centered "Something went wrong" view with a Retry button. If the FAB ever errors during render — say, a future regression puts it outside NavigationContainer again — that full-screen fallback would displace real UI. A FAB failure should be invisible to the user. Telemetry still captures it vialogger.errorincomponentDidCatch.ErrorBoundary.tsx— extendPropswith an optionalrenderFallbackrender-prop. When provided, it is used instead of the default centered fallback. Default behavior and all existing call sites unchanged.AmicusFabErrorFallback.tsx— new component that rendersnull.App.tsx— the AmicusFabErrorBoundarynow usesrenderFallback={AmicusFabErrorFallback}in place offallbackMessage.2. Provider-tree smoke test
app/__tests__/App.providerTree.test.tsx— mounts<App />with the real@react-navigation/native(not the non-throwingjest.setup.jsstub), waits fordbStatus -> 'ready', and asserts the full tree composes without throwing. This is the test that would have caught #1557's root cause before it reached TestFlight.Heavy / native-bound / out-of-scope dependencies (
RootNavigator, stores, DB init, Sentry, the notification router, the crash handler) are mocked. TheNavigationContainercomposition itself runs for real — that's the point.Validation
npx tsc --noEmit— cleannpm run lint— cleannpm test— 466 suites, 3433 tests pass (1 new smoke test, no regressions)npx jest --testPathPattern "AmicusFab"— 9 tests passnpx jest --testPathPattern "App.providerTree"— 1 test passesWhat this PR does NOT do
AmicusFab.tsx— the defensive try/catch from fix(amicus): prevent AmicusFab crash when mounted outside NavigationContainer #1557 stays as belt-and-suspenders regression prevention.AmicusPeekSheet.tsx— itsuseNavigationStatecall now succeeds naturally because AmicusFab (and therefore the sheet, rendered as its child) is insideNavigationContainer.Follow-ups that remain open
useNavigation()/useNavigationState()/useRoute()calls.DEV_GUIDE.mdwith a code-review checklist item.