docs: make provider dependency chain explicit with documentation and tests
This addresses issue #19 by making the implicit provider dependency order explicit and order-sensitive. Changes: 1. Created PROVIDER_ORDER.md - comprehensive documentation explaining: - The provider hierarchy from outermost to innermost - Why each provider must be at its position - Order-sensitive pitfalls and what would break - Guidelines for adding new providers in the future 2. Added provider composition tests (providerComposition.test.tsx): - 13 comprehensive tests validating provider order and dependencies - Tests verify all providers mount correctly - Tests check that hooks only work inside correct providers - Tests validate async initialization (AuthProvider, TimezoneProvider) - Tests verify theme persistence and notification propagation 3. Updated App.tsx with inline documentation: - Added detailed provider order contract in JSDoc header - Inline comments explaining each provider's position - Reference to PROVIDER_ORDER.md for detailed rationale 4. Updated Web-Development.md: - Added new section 5.5 'Provider Order Contract' - Documents provider hierarchy and rationale - Links to comprehensive provider documentation - References regression test suite All tests pass. TypeScript compilation succeeds. Build succeeds. The provider order is now explicit and future refactors can validate compliance through the regression test suite. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -1,10 +1,16 @@
|
||||
/**
|
||||
* Application root component.
|
||||
*
|
||||
* Wraps the entire application in:
|
||||
* 1. `FluentProvider` — supplies the Fluent UI theme and design tokens.
|
||||
* 2. `BrowserRouter` — enables client-side routing via React Router.
|
||||
* 3. `AuthProvider` — manages session state and exposes `useAuth()`.
|
||||
* Provider order (see `src/providers/PROVIDER_ORDER.md` for detailed contract):
|
||||
* 1. `ThemeProvider` — OUTERMOST; provides theme context to AppContents
|
||||
* 2. `FluentProvider` — supplies Fluent UI theme and design tokens
|
||||
* 3. `NotificationProvider` — provides notification service to all descendants
|
||||
* 4. `ErrorBoundary` — catches catastrophic errors
|
||||
* 5. `BrowserRouter` — enables client-side routing via React Router
|
||||
* 6. `AuthProvider` — manages session state; validates on mount; uses useNavigate()
|
||||
* 7. `TimezoneProvider` — INNERMOST (inside protected routes); fetches timezone after auth
|
||||
*
|
||||
* CRITICAL: Provider order is order-sensitive. See PROVIDER_ORDER.md before refactoring.
|
||||
*
|
||||
* Routes:
|
||||
* - `/setup` — first-run setup wizard (always accessible; redirects to /login if already done)
|
||||
@@ -51,22 +57,36 @@ const BlocklistsPage = lazy(() => import("./pages/BlocklistsPage").then((m) => (
|
||||
|
||||
/**
|
||||
* Root application component — mounts providers and top-level routes.
|
||||
*
|
||||
* Provider stack (see PROVIDER_ORDER.md for detailed contract):
|
||||
* - FluentProvider (2) — receives theme from useThemeMode()
|
||||
* - NotificationProvider (3) — provides notification service
|
||||
* - ErrorBoundary (4) — catches catastrophic errors
|
||||
* - BrowserRouter (5) — enables routing
|
||||
* - AuthProvider (6) — session validation; uses useNavigate()
|
||||
* - TimezoneProvider (7) — inside protected routes only
|
||||
*/
|
||||
function AppContents(): React.JSX.Element {
|
||||
const { colorMode } = useThemeMode();
|
||||
const theme = colorMode === "dark" ? darkTheme : lightTheme;
|
||||
|
||||
return (
|
||||
// 2. FluentProvider — supplies Fluent UI theme and tokens
|
||||
<FluentProvider theme={theme}>
|
||||
{/* 3. NotificationProvider — makes notification service available */}
|
||||
<NotificationProvider>
|
||||
{/* 4. ErrorBoundary — catches catastrophic errors that would crash the app */}
|
||||
<ErrorBoundary
|
||||
title="Application Error"
|
||||
message="The application encountered a critical error. Reloading may help."
|
||||
isFullPage={true}
|
||||
>
|
||||
{/* Notification container must be rendered inside ErrorBoundary */}
|
||||
<NotificationContainer />
|
||||
{/* 5. BrowserRouter — enables routing; required by AuthProvider's useNavigate() */}
|
||||
<BrowserRouter future={{ v7_startTransition: true, v7_relativeSplatPath: true }}>
|
||||
<Suspense fallback={<Spinner size="large" label="Loading…" />}>
|
||||
{/* 6. AuthProvider — validates session on mount; must be inside BrowserRouter */}
|
||||
<AuthProvider>
|
||||
<Routes>
|
||||
{/* Setup wizard — always accessible; redirects to /login if already done */}
|
||||
@@ -96,6 +116,7 @@ function AppContents(): React.JSX.Element {
|
||||
element={
|
||||
<SetupGuard>
|
||||
<RequireAuth>
|
||||
{/* 7. TimezoneProvider — INNERMOST; fetches timezone after auth validation */}
|
||||
<TimezoneProvider>
|
||||
<MainLayout />
|
||||
</TimezoneProvider>
|
||||
@@ -174,6 +195,7 @@ function AppContents(): React.JSX.Element {
|
||||
}
|
||||
|
||||
function App(): React.JSX.Element {
|
||||
// ThemeProvider (1. OUTERMOST) — provides theme context needed by AppContents
|
||||
return (
|
||||
<ThemeProvider>
|
||||
<AppContents />
|
||||
|
||||
Reference in New Issue
Block a user