use-swr-refresh.test.tsx
Overview
use-swr-refresh.test.tsx is a comprehensive test suite for verifying the behavior of the useSWR React hook's refresh functionality, particularly focusing on the refreshInterval option and related mechanisms such as deduplication, dynamic interval changes, custom comparison, and key changes during interval-based fetching.
This file uses Jest with React Testing Library to simulate component rendering, user interactions, and timer manipulations (using Jest’s fake timers) to ensure that the useSWR hook refreshes data correctly at specified intervals, handles deduplication properly, and respects dynamic changes to refresh intervals or keys.
Detailed Explanation of Contents
Utilities and Imports
act,fireEvent,screenfrom@testing-library/react
Used for rendering components, firing DOM events, and querying rendered elements.React and its hooks (
useState)
To create test components with state.useSWR,SWRConfig,useSWRConfigfrom swr
The hook under test and related context/configuration hooks.createKey,renderWithConfig, sleep from ./utils
Helper functions likely defined elsewhere:createKey: Generates unique keys for SWR cache.renderWithConfig: Renders components wrapped with necessary SWR context.sleep: Async delay helper.
advanceTimers(ms)
A helper async function that advances Jest’s fake timers bymsmilliseconds and allows microtasks to flush, simulating the passage of time in tests.
Test Suite: useSWR - refresh
Tests are wrapped inside a describe block named "useSWR - refresh", with Jest's fake timers enabled to control asynchronous timing behavior deterministically.
Individual Tests
1. should rerender automatically on interval
Purpose:
Verify thatuseSWRre-fetches data repeatedly at the specifiedrefreshInterval.Mechanism:
Uses a counter as data.
Sets
refreshIntervalto 200ms anddedupingIntervalto 100ms.Advances timers and asserts the rendered count increments accordingly.
Key Points:
Ensures refresh triggers after
refreshInterval.Deduplication prevents unnecessary fetches within
dedupingInterval.
2. should dedupe requests combined with intervals
Purpose:
Test that deduplication works correctly when combined with refresh intervals.Mechanism:
Refresh interval 100ms, deduping interval 500ms.
Multiple timer advances verify that fetches are skipped/deduped within deduping interval.
3. should update data upon interval changes
Purpose:
Test dynamic update ofrefreshIntervalwhen it changes during component lifecycle.Mechanism:
Uses React state to control
refreshInterval.Clicking the div cycles interval between 100, 150, 200, and 0 (stop).
Asserts data updates respect the new interval values.
4. should update data upon interval changes -- changes happened during revalidate
Purpose:
Test interval changes happening during an ongoing revalidation.Mechanism:
Uses a
flagstate to control polling stop.onSuccessincrements the flag; polling stops when threshold reached.Clicking resets flag and restarts polling.
Asserts correct behavior despite interval changes during revalidation.
5. should allow use custom compare method
Purpose:
Verify that a customcomparefunction can be used to control data equality checks, affecting whether data updates trigger re-renders.Mechanism:
Custom compare function compares only the
versionfield in data.Fetcher returns objects with incrementing
timestampand fixedversion.Clicking button triggers mutate.
Asserts that data with same
versiondoes not cause re-render even if timestamp changes.
6. custom compare should only be used for comparing data
Purpose:
Ensure custom compare function is only used for data comparison, and SWR’s internal compare mechanism is still respected.Mechanism:
Records all calls to custom compare function with parameters.
Asserts the pattern of calls matches expected snapshots.
Clicking "change" triggers mutate and fetcher.
7. should not let the previous interval timer to set new timer if key changes too fast
Purpose:
Confirm that when the SWR key changes rapidly, previous interval timers do not incorrectly schedule new fetches.Mechanism:
Uses a key that changes on button clicks.
Fetcher simulates async delay.
Advances timers and clicks button to change key.
Asserts fetcher is called correctly with new keys and no overlapping timers.
8. should not call onSuccess from the previous interval if key has changed
Purpose:
Ensure thatonSuccesscallbacks from previous intervals don't fire after the key has changed.Mechanism:
Similar to previous test but focuses on
onSuccesscalls.Uses a key that includes a count.
Clicking button increments count (key changes).
Asserts
onSuccessis called only for the current key.
9. should allow using function as an interval
Purpose:
Verify thatrefreshIntervalcan be a function returning interval duration.Mechanism:
refreshIntervalreturns a fixed value (200ms).Asserts data refreshes accordingly.
10. should pass updated data to refreshInterval
Purpose:
Test thatrefreshIntervalfunction receives updated data as an argument.Mechanism:
refreshIntervaluses the current data value to compute interval.Asserts refresh happens after intervals based on data value.
11. should pass updated data to refreshInterval, when refreshInterval is constant function
Purpose:
Verify that a constant function used asrefreshIntervalis called with updated data.Mechanism:
Function returns 1000ms unless data > 5, then 0 (stop).
Asserts function is called with correct data.
12. should disable refresh if function returns 0
Purpose:
Check that returning 0 fromrefreshIntervaldisables refresh.Mechanism:
refreshIntervalalways returns 0.Asserts no data updates occur after initial mount.
Important Implementation Details and Algorithms
Fake Timers:
The tests rely on Jest’s fake timers to control asynchronous timing behavior precisely, enabling simulation of intervals and timeouts without real delays.Deduplication:
ThededupingIntervaloption is critical in tests to avoid redundant fetches within a short time window. This is tested extensively to confirm correct behavior.Dynamic Interval Handling:
The tests verify thatuseSWRcorrectly handles changes torefreshIntervalduring runtime, including cases when the interval function depends on the current data.Custom Data Comparison:
The ability to inject a customcomparefunction to control when updates are considered meaningful is tested, ensuring that unnecessary re-renders are avoided.Handling Key Changes During Refresh:
The tests ensure that when the key changes rapidly or during an ongoing refresh, the previous timers and callbacks do not cause stale updates or side effects.
Interaction with Other Parts of the System
useSWRHook:
The file tests features of theuseSWRhook from the SWR library, focusing on refresh-related options.Helper Utilities:
It usescreateKey,renderWithConfig, and sleep utilities from a local utils module for key generation, rendering with SWR config context, and simulating async delays.React Components:
The tests create small React components (Page,App) that useuseSWRwith various configurations to simulate real-world usage scenarios.Jest and React Testing Library:
The file integrates Jest’s fake timers and React Testing Library's methods to simulate user interaction and time-based events.
Usage Examples
Basic Auto-Refresh Test Example
// Component that increments count every 200ms
function Page() {
const { data } = useSWR('key', () => count++, {
refreshInterval: 200,
dedupingInterval: 100
});
return <div>count: {data}</div>;
}
// Render and advance timers to observe automatic refresh
renderWithConfig(<Page />);
await act(() => advanceTimers(200));
screen.getByText('count: 1');
Using Custom Compare Function
const fetcher = () => ({ timestamp: Date.now(), version: '1.0' });
useSWR('key', fetcher, {
compare: (a, b) => a?.version === b?.version
});
Dynamic Refresh Interval Based on Data
useSWR('key', fetcher, {
refreshInterval: (data) => data * 1000 // interval changes as data changes
});
Mermaid Diagram: Test File Structure and Workflow
flowchart TD
A[useSWR - refresh Test Suite] --> B1[Test: rerender on interval]
A --> B2[Test: dedupe requests + intervals]
A --> B3[Test: update on interval changes]
A --> B4[Test: update on interval changes during revalidate]
A --> B5[Test: custom compare method]
A --> B6[Test: custom compare only for data]
A --> B7[Test: no new timer if key changes too fast]
A --> B8[Test: no onSuccess from previous interval if key changed]
A --> B9[Test: function as interval]
A --> B10[Test: pass updated data to refreshInterval]
A --> B11[Test: constant function refreshInterval called with updated data]
A --> B12[Test: disable refresh if interval returns 0]
B1 --> C1[Component with count state]
B3 --> C3[Component with refreshInterval state]
B5 --> C5[Component with custom compare]
B7 --> C7[Component with key-changing state]
Summary
This test file ensures that the useSWR hook's refresh capabilities are robust, performant, and flexible. It covers automatic interval refresh, deduplication, dynamic intervals, custom data comparison, key changes during refresh, and disabling refresh. The tests simulate realistic use cases and edge cases, using Jest's fake timers to reliably test timing-dependent features.
This thorough testing contributes to the stability of SWR’s data fetching and caching behavior in applications that rely on automatic background refreshes of remote data.