use-swr-streaming-ssr.test.tsx
Overview
This file contains automated tests that verify the behavior of the useSWR React hook in a streaming Server-Side Rendering (SSR) and hydration context. The tests specifically focus on ensuring that client-side hydration matches the server-rendered HTML when using SWR (stale-while-revalidate) for data fetching and caching. It also explores complex scenarios of partial hydration with streaming Suspense boundaries, though with a known limitation related to JSDOM environment support.
The key functionalities tested are:
Hydrating a React component that uses
useSWRwith data fetched asynchronously.Ensuring that the client cache state matches the SSR output.
Testing streaming and partial hydration scenarios with Suspense (marked as failing due to environment limitations).
This test file leverages utility functions from a local ./utils module to handle key creation, response simulation, rendering with configuration, hydration, and error mocking.
Detailed Explanation
Imports and Utilities
actfrom@testing-library/react: Ensures React state updates are processed before assertions.Suspensefromreact: Used to test React Suspense boundaries.useSWRfromswr: The hook under test, which handles data fetching and caching.Various helpers from
./utils:createKey(): Generates unique keys for SWR cache.createResponse(data, options): Simulates asynchronous data fetching with optional delay.renderWithConfig(),hydrateWithConfig(): Custom render/hydrate utilities for SSR testing.mockConsoleForHydrationErrors(): Suppresses hydration warnings during tests.sleep(ms): Utility to pause execution for a specified time.
Test Suite: useSWR - streaming
This suite contains two main test cases focusing on hydration and streaming SSR with useSWR.
afterEach Hook
Resets all Jest mocks after every test to avoid side effects.
Test Case 1: should match ssr result when hydrating
Purpose:
Verify that hydrating a component using useSWR produces the same content as the SSR HTML.
Implementation Details:
Uses
mockConsoleForHydrationErrorsto suppress React hydration warnings.Blockcomponent fetches data asynchronously withuseSWRusing a unique key.The component renders the fetched data or
"undefined"if data is not yet available.A container with initial inner HTML
<div>undefined</div>simulates server-rendered markup.The component is hydrated into this container using
hydrateWithConfig.After hydration, the console mock is restored.
Parameters: None (test case).
Return: Promise — test completes asynchronously.
Example Usage:
const key = createKey();
function Block() {
const { data } = useSWR(key, () => createResponse('SWR', { delay: 10 }));
return <div>{data || 'undefined'}</div>;
}
// Hydrate Block into container with SSR markup.
await hydrateWithConfig(<Block />, container);
Test Case 2: should match the ssr result when streaming and partially hydrating (marked .failing)
Purpose:
Test partial hydration behavior during streaming SSR with Suspense boundaries and multiple useSWR instances.
Important Note:
This test is marked as .failing because JSDOM (the default testing environment) cannot simulate streaming SSR and partial hydration accurately. It requires a real browser environment.
Implementation Details:
Defines a component
Blockwith props:suspense(boolean): enables Suspense mode in SWR.delay(number): simulates data fetching delay.id(string): unique identifier for each block instance.
The component uses
useSWRto fetch data asynchronously with or without Suspense.Tracks data during hydration in
dataDuringHydrationobject keyed byid.Renders two blocks:
a: Suspense disabled, delay 10ms (hydrated first).b: Suspense enabled, delay 20ms (hydrated later inside<Suspense>).
Expects that both
aandbwill initially render"undefined"during SSR because data fetching does not occur server-side.After simulated streaming finishes (waiting 50ms), asserts that hydration data matches expectations.
Parameters: None (test case).
Return: Promise — asynchronous test.
Example Usage:
renderWithConfig(
<>
<Block id="a" suspense={false} delay={10} />
<Suspense fallback={null}>
<Block id="b" suspense={true} delay={20} />
</Suspense>
</>
);
await act(() => sleep(50));
expect(dataDuringHydration).toEqual({ a: 'undefined', b: 'undefined' });
Important Implementation Details
Hydration Testing: The tests simulate hydrating React components with server-rendered HTML to ensure that client-side state and UI are consistent with server output.
Streaming & Partial Hydration: The second test attempts to model real-world streaming SSR where parts of the UI hydrate at different times and data fetches may overlap or be isolated.
Mocking Console Errors: Hydration warnings are suppressed temporarily to avoid noisy test output during expected mismatches.
Data Fetching Simulation: The
createResponseutility likely returns a Promise that resolves after a delay, mimicking network latency.
Interaction with Other System Parts
The file depends on utilities (
./utils) for simulating SWR keys, responses, and rendering environment, which are crucial for setting up the test environment.It tests
useSWRhook behavior, which is part of the SWR library responsible for data fetching and caching in React apps.The hydration and rendering utilities imply integration with React Testing Library or a custom test harness that supports SSR and hydration simulation.
The tests provide validation for the SWR integration in an SSR streaming React application, ensuring consistency between server and client renders.
Visual Diagram
flowchart TD
A[useSWR - streaming test suite]
A --> B[afterEach: jest mocks reset]
A --> C[Test 1: Hydration match]
A --> D[Test 2: Streaming & Partial Hydration (failing)]
C --> C1[Create unique key]
C --> C2[Define Block component]
C2 --> C3[useSWR fetches data with delay]
C3 --> C4[Render data or 'undefined']
C --> C5[Hydrate Block into container]
C --> C6[Check hydration matches SSR]
D --> D1[Create unique key]
D --> D2[Define Block component with id, suspense, delay]
D2 --> D3[useSWR fetches data with delay and suspense option]
D3 --> D4[Track dataDuringHydration per id]
D --> D5[Render two Block instances: a (no suspense), b (with suspense)]
D --> D6[Wrap b in Suspense boundary]
D --> D7[Wait for streaming to finish]
D --> D8[Assert dataDuringHydration matches SSR expectations]
subgraph Utils
U1[createKey()]
U2[createResponse()]
U3[renderWithConfig()]
U4[hydrateWithConfig()]
U5[mockConsoleForHydrationErrors()]
U6[sleep()]
end
C1 --> U1
C3 --> U2
C5 --> U4
C --> U5
D1 --> U1
D3 --> U2
D5 --> U3
D7 --> U6
Summary
This test file rigorously verifies that the useSWR hook’s behavior during SSR streaming and client hydration is consistent and error-free. It uses custom utilities to simulate asynchronous data responses and rendering environments, with tests designed to catch hydration mismatches and streaming hydration edge cases. Although limited by the JSDOM testing environment for streaming tests, it lays the foundation for reliable SSR hydration testing in React applications using SWR.
If you need further details on the utilities or the SWR hook itself, please refer to their respective documentation or source code modules.