use-swr-promise.test.tsx
Overview
This file contains a suite of automated tests for verifying the behavior of the useSWR React hook when used with promises as fallback data or fallback values. It specifically tests scenarios where promises are passed as fallback values in SWRConfig or as fallbackData in the hook's options, focusing on async data resolution, suspense integration, and error handling.
The tests ensure that useSWR correctly supports promise-based fallbacks by:
Rendering initial data from fallback promises.
Updating rendered data once the promise resolves.
Suspending component rendering during fallback promise resolution.
Handling errors thrown by fallback promises gracefully.
Managing multiple components sharing the same pending fallback promise.
These tests validate the integration of React Suspense and Error Boundaries with the SWR cache and data fetching mechanism when promises are used as fallback values.
Detailed Explanations
Imports
act, screen from
@testing-library/react: Utilities for simulating React state updates and querying DOM elements.useSWR,SWRConfigfromswr: The hook and configuration provider for data fetching.Utility functions from
./utils:createKey(): Generates unique keys for SWR.createResponse(value, options): Creates a promise that resolves or rejects with a value after a delay.renderWithConfig(): Renders React components with necessary SWR context.sleep(ms): Returns a promise that resolves after a delay.
React's
Suspensecomponent for suspense handling.ErrorBoundaryfrom react-error-boundary to catch errors in components.
Test Suite: describe('useSWR - promise', ...)
This suite contains six test cases that cover different scenarios of using promises as fallback data within useSWR.
Test Case 1: 'should allow passing promises as fallback'
Purpose:
Tests that useSWR supports passing a promise as a fallback value via the fallback prop in SWRConfig.
Implementation details:
A unique key is created.
fetchData is a promise resolving to 'initial data' after 100ms.
The SWR config fallback provides this promise for the key.
The Page component calls
useSWRwith the key and a fetcher returning a new promise resolving'new data'.On first render, the data should come from the fallback promise ('initial data').
After waiting for fetcher resolution (100ms), the data updates to
'new data'.Uses
screen.findByTextto verify UI updates and act + sleep to await async resolution.
Parameters: None (test scope).
Return: None (test assertion).
Usage Example:
Test code shows usage of useSWR with a promise fallback in SWRConfig.
Test Case 2: 'should allow passing promises as fallbackData'
Purpose:
Tests passing a promise as fallbackData option directly in the useSWR hook.
Details:
Similar to test 1, but fallback promise provided as
fallbackDatain hook options.Verifies initial render shows fallback promise resolved value.
Checks data update after fetcher promise resolves.
Test Case 3: 'should suspend when resolving the fallback promise'
Purpose:
Verifies that useSWR suspends rendering while resolving a fallback promise when used with React's Suspense.
Details:
Uses
Suspensewith a fallback UI.
Initial fallback promise delays 100ms.
Checks that UI first renders the suspense fallback.
After resolution, renders the data from the fallback.
Then updates to new data after fetcher resolves.
Test Case 4: 'should handle errors with fallback promises'
Purpose:
Tests error handling when fallback promise rejects.
Details:
Uses
ErrorBoundaryto catch errors thrown by rejected fallback promise.Fallback promise rejects with an Error('error') after 100ms.
Suspense fallback
shown at first.
After rejection, error boundary fallback
is displayed.
Console errors are suppressed during test to keep output clean.
Test Case 5: 'should handle same fallback promise that is already pending'
Purpose:
Tests that multiple components sharing the same pending fallback promise synchronize correctly.
Details:
Two components rendered inside the same
SWRConfigwith shared fallback promise.Both suspend initially, showing loading.
After promise resolves, both components render the same resolved data.
Verifies that shared promises in fallback are handled without redundant fetches.
Important Implementation Details
Promise Fallbacks: This test file verifies that fallback values and fallbackData can be promises, which SWR recognizes and unwraps asynchronously.
Suspense Integration: Tests confirm that SWR suspends rendering correctly when fallback promises are pending, enabling React Suspense support.
Error Boundaries: Errors from rejected fallback promises propagate correctly to error boundaries.
Shared Promises: Multiple consumers sharing the same fallback promise properly wait and synchronize on the promise resolution.
Utilities: The createResponse utility is key for simulating delayed promise resolutions or rejections, allowing control over async timing.
Interaction with Other Parts of the System
useSWRHook: Core subject under test, responsible for data fetching and caching.SWRConfigProvider: Supplies configuration and fallback values for SWR instances.Utilities (
./utils): Provide helper functions for key generation, promise creation, and rendering setup, abstracting test scaffolding.React Suspense & Error Boundary: Used to test integration between SWR async data and React rendering lifecycle.
Testing Library: Used for DOM querying and simulating async React updates.
This file is purely for testing and verification; it does not export components or logic for production use. It ensures the useSWR hook behaves correctly under promise fallback conditions.
Visual Diagram
flowchart TD
A[useSWR hook] -->|Uses| B[SWRConfig fallback / fallbackData]
B -->|Can be Promise| C[Promise resolving to data]
A -->|Returns| D[data]
A -->|Triggers| E[Component Render]
E -->|Suspense pending| F[Suspense fallback UI]
E -->|Error thrown| G[ErrorBoundary fallback UI]
H[Multiple components] -->|Share| B
C -->|Resolves or rejects| D
Diagram Explanation:
useSWRconsumes fallback values fromSWRConfigor hook options.These fallback values can be promises.
While promises are pending, components may suspend rendering.
Errors from promises propagate to Error Boundaries.
Multiple components can share the same fallback promise to synchronize data.
Summary
This test file rigorously validates that the useSWR hook supports promise-based fallbacks, properly integrates with React Suspense and Error Boundaries, and correctly handles synchronization when multiple components share the same fallback promise. The tests rely on utility functions to simulate delayed async data and ensure UI updates match expected data states. This makes the file crucial for ensuring SWR's robustness in handling asynchronous initial states in React applications.