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:

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


Test Suite: useSWR - streaming

This suite contains two main test cases focusing on hydration and streaming SSR with useSWR.

afterEach Hook


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:

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:

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


Interaction with Other System Parts


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.