use-swr-server.test.tsx
Overview
This file contains test cases designed to validate the behavior of the useSWR React hook in server-side rendering (SSR) environments, specifically targeting scenarios involving React versions less than or equal to 17 and SSR contexts. It focuses on ensuring that the useSWR hook correctly handles suspense mode without a fallback during SSR, by verifying that appropriate errors are thrown and caught.
The tests simulate a server environment by manipulating the global window object and leveraging Jest's module isolation features. It also utilizes React's Suspense and an ErrorBoundary from react-error-boundary to test the hook's error handling mechanisms during SSR.
Detailed Explanation
Imports
screen, renderfrom@testing-library/react
Utilities for rendering React components and querying the DOM in test environments.Suspensefromreact
React component that allows waiting for some code to load or data to be fetched.ErrorBoundaryfromreact-error-boundary
Component to catch JavaScript errors anywhere in their child component tree and display a fallback UI.jest.mock('react', ...)
Addresses a known Jest issue (https://github.com/jestjs/jest/issues/11471) by mocking React while preserving the actual implementation.
Function: withServer
async function withServer(runner: () => Promise<void>)
Purpose
A utility function to run a test case inside an isolated module environment using Jest's isolateModulesAsync. This ensures that module state does not leak between tests, which is critical for testing server-side rendering behaviors where modules may behave differently depending on environment globals.
Parameters
runner: An asynchronous function containing the test logic to run within the isolated module context.
Usage Example
await withServer(async () => {
// test logic inside isolated module environment
});
Return Value
Returns a
Promise<void>that resolves when the runner completes.
Test Suite: 'useSWR - SSR'
This suite contains tests related to the useSWR hook's behavior during SSR.
beforeAll Hook
Sets up the global environment to simulate a server context by:
Adding a
Denoproperty to the globalwindowobject (used as a marker for SSR).The commented-out line shows an alternative approach—deleting the
windowobject entirely.
afterAll Hook
Cleans up after tests by removing the added Deno property from the global window object, restoring the environment.
Test Case: 'should enable the IS_SERVER flag - suspense on server without fallback'
This test validates that when useSWR is used with suspense mode enabled during SSR without providing a fallback, it triggers the expected error.
Test Flow
Uses
withServerto run the test in an isolated module environment.Mocks
console.errorto suppress error logs during the test.Dynamically imports
useSWRfrom theswrpackage.Defines a unique key using
Math.random().toString().Defines a React component
Pagethat usesuseSWRwith suspense enabled.Renders the
Pagecomponent wrapped in:ErrorBoundarywith a fallback renderer that logs errors and displays the error message.Suspenseto support suspense mode rendering.
Asserts that the error message
"Fallback data is required when using Suspense in SSR."is rendered, confirming that the hook correctly enforces fallback requirements in SSR suspense mode.
Key Implementation Details
The test verifies the internal
IS_SERVERflag behavior ofuseSWRby manipulating the global environment and simulating SSR.The use of
ErrorBoundaryandSuspensetogether mimics real-world React suspense error handling.The dynamic import of
useSWRinside the isolated context ensures fresh module state per test run.
Implementation Details and Algorithms
Module Isolation:
Using Jest'sjest.isolateModulesAsyncto run tests with separate module instances to prevent shared state and simulate SSR environments accurately.Global Environment Mocking:
The test fakes a server environment by adding aDenoproperty to the globalwindowobject, which is a common way to detect non-browser environments.Error Boundary and Suspense Integration:
The component tree includes anErrorBoundaryto catch thrown errors fromuseSWRwhen suspense is used incorrectly, andSuspenseto enable suspense-mode rendering.Dynamic Key Generation:
The hook's key is randomized to avoid caching effects between test runs.
Interaction with Other System Components
useSWRHook (fromswrpackage):
The hook under test; this test file ensures it behaves correctly in SSR and suspense contexts.React & React Suspense:
Utilizes React components and features likeSuspenseto simulate React's data fetching and error handling during rendering.Testing Library (
@testing-library/react):
Used for rendering components and querying the DOM in tests.Jest Testing Framework:
Provides the test environment, mocks, and module isolation capabilities.react-error-boundary:
Provides theErrorBoundarycomponent used to capture and assert errors thrown byuseSWR.
Example Usage in Test
await withServer(async () => {
const useSWR = (await import('swr')).default;
const key = 'my-key';
function Page() {
const { data } = useSWR(key, () => 'data', { suspense: true });
return <div>{data || 'empty'}</div>;
}
render(
<ErrorBoundary fallbackRender={({ error }) => <div>{error.message}</div>}>
<Suspense>
<Page />
</Suspense>
</ErrorBoundary>
);
await screen.findByText('Fallback data is required when using Suspense in SSR.');
});
Visual Diagram
flowchart TD
A[Start Test Suite: 'useSWR - SSR'] --> B[beforeAll: Mock Global Window Environment]
B --> C[Run Test: 'should enable IS_SERVER flag']
C --> D[withServer: isolateModulesAsync]
D --> E[Import useSWR dynamically]
E --> F[Define Page component using useSWR with suspense]
F --> G[Render Page inside Suspense and ErrorBoundary]
G --> H[ErrorBoundary catches error thrown by useSWR]
H --> I[Assert error message "Fallback data is required..."]
I --> J[afterAll: Clean up global environment]
Summary
This test file ensures
useSWRbehaves correctly in SSR environments with React versions <= 17.It focuses on suspense mode without fallback, verifying that errors are thrown and caught properly.
Uses Jest's module isolation and global environment mocking to simulate SSR.
Leverages React's
SuspenseandErrorBoundaryfor testing error handling in suspense mode.Provides a robust approach to testing SSR-specific behavior of
useSWR.
This file is crucial for maintaining stable SSR support in the swr library, preventing common pitfalls when suspense mode is used incorrectly on the server side.