use-swr-subscription.test.tsx
Overview
This file contains unit tests for the useSWRSubscription React hook from the swr/subscription package. The hook is designed to enable React components to subscribe to external data sources or streams with automatic revalidation, error handling, and deduplication of subscriptions.
The tests verify the correct behavior of useSWRSubscription in various scenarios, including:
Receiving and updating streamed data over time.
Handling errors emitted by the subscription.
Passing original keys to the subscription function.
Supporting dynamic updates of the subscription key.
Deduplicating multiple subscriptions to the same key.
Coexisting with
useSWRwithout state conflicts.Supporting singleton subscriptions with manual event emitters.
Enforcing the requirement that the subscription function returns a dispose/unsubscribe function.
These tests use React Testing Library and Jest to simulate asynchronous subscription behavior, user interactions, and rendering verification.
Detailed Explanation of Tests and Components
Imports
act,fireEvent, screen from@testing-library/react: Utilities for rendering components, simulating events, and querying the DOM.sleep,renderWithConfig,createKeyfrom local./utils: Helper functions for waiting, rendering with context/configuration, and generating unique keys.useSWRSubscriptionfrom swr/subscription: The hook under test.useSWRfromswr: A related hook tested for compatibility.React hooks:
useEffectanduseState.ErrorBoundaryfromreact-error-boundary: For catching errors in React components.
Test Suite: describe('useSWRSubscription', () => {...})
1. Test: 'should update the state'
Purpose: Verify that the hook updates the component state with streaming data and handles errors correctly.
Key Function:
subscribe(key, { next })sets an interval to emit incremental data or error after 3 updates.Component:
PageusesuseSWRSubscriptionwith a fallback.Assertions:
Initial render shows fallback data.
Data updates every 100ms with concatenated key and count.
On the 4th emission, an error is emitted and displayed.
After error, data continues updating, and error resets.
Usage Example:
const { data, error } = useSWRSubscription(key, subscribe, { fallbackData: 'fallback' });
2. Test: 'should pass the origin keys'
Purpose: Confirm that the subscription receives the original key array (for dynamic keys).
Key Difference: Subscription accesses
key[0]because the key is a function returning an array.Behavior: Same as first test but verifies key is passed correctly.
Usage: Passing keys as a function returning array is supported.
3. Test: 'should support updating keys'
Purpose: Test that changing the subscription key triggers a new subscription.
Mechanism: Uses
useStateto update key after 100ms.Verification: Only subscribes for defined keys, ignoring
undefined.Effect: Subscription function receives the updated key.
4. Test: 'should deduplicate subscriptions'
Purpose: Ensure multiple
useSWRSubscriptioncalls with the same key reuse the same subscription instead of duplicating.Verification: Subscription function called exactly once.
Effect: Performance optimization via deduplication.
5. Test: 'should not conflict with useSWR state'
Purpose: Confirm
useSWRSubscriptionstate does not interfere withuseSWRfor the same key.Component: Renders both hooks simultaneously.
Verification: Both hooks maintain independent data states.
6. Test: 'should support singleton subscription'
Purpose: Demonstrates a manual subscription pattern where a callback is registered and triggered outside the hook.
Mechanism:
Singleton callback function updated with new subscribers.
External
emitfunction triggers data updates.Key state is updated via button, causing re-subscription.
Effect: Shows flexibility to wrap custom subscription logic.
7. Test: 'should require a dispose function'
Purpose: Ensures subscription functions return a cleanup function.
Behavior: If not, an error is thrown and caught by
ErrorBoundary.Verification: Error message is rendered.
Importance: Prevents resource leaks by enforcing proper unsubscribe.
Important Implementation Details and Algorithms
Subscription Function Pattern: The core pattern for subscriptions is a function
(key, { next }) => unsubscribeFn, where:key: the subscription key (string or array).{ next }: callback to emit data or error.unsubscribeFn: a function to clean up resources.
Interval-based Data Emission: Many tests use
setIntervalto simulate streaming data and errors asynchronously.Deduplication: Multiple calls to
useSWRSubscriptionwith the same key share a single underlying subscription, reducing redundant network or resource usage.Error Handling: Errors emitted via
next(err)are surfaced to the component and can be handled or displayed.React Integration: Uses React hooks (
useState,useEffect) to manage subscription lifecycle and state updates.Fallback Data: Allows specifying initial data before subscription emits values.
Testing Utilities: Uses
actto batch React updates andsleepfor timing control.
Interaction With Other System Parts
useSWRSubscriptionHook: This file tests its integration and behavior in React components.useSWRHook: Tests compatibility and ensures no state conflicts.renderWithConfigUtility: Likely sets up a React testing environment with necessary providers or SWR config.createKeyUtility: Generates unique keys for subscriptions to avoid test collisions.ErrorBoundary: Used to catch errors thrown by improper subscription implementations.
This file acts as a test suite ensuring the robustness of useSWRSubscription for consuming components and for integration within the larger SWR ecosystem.
Key Functions and Components Summary
Name | Type | Parameters | Returns | Description |
|---|---|---|---|---|
| function |
|
| Defines a data subscription, calls |
| React Comp | None (uses hook internally) | JSX Element | Example component consuming |
| custom Hook |
| SWR subscription result | Wraps |
| React Comp | None | JSX Element | Demonstrates subscription data updates and key changes with user interaction. |
Usage Examples
Basic Subscription Example:
function subscribe(key, { next }) {
const interval = setInterval(() => {
next(undefined, `${key}-${Date.now()}`);
}, 1000);
return () => clearInterval(interval);
}
function Page() {
const { data, error } = useSWRSubscription('my-key', subscribe, {
fallbackData: 'Loading...'
});
if (error) return <div>Error: {error.message}</div>;
return <div>Data: {data}</div>;
}
Mermaid Diagram: Component Interaction and Workflow
This flowchart shows the relationship between the main functions, React components, and the hook usage pattern in the test file:
flowchart TD
subgraph Subscription Flow
A[subscribe(key, { next })] -->|calls next(data or error)| B[useSWRSubscription Hook]
B --> C[React Component (Page, App)]
C --> D[Render UI with data or error]
end
subgraph Test Utilities
E[renderWithConfig] --> C
F[sleep & act] --> C
G[fireEvent] --> C
end
subgraph Error Handling
H[subscribe returns dispose fn] -->|enforced| B
I[Error Boundary] -->|catches errors| C
end
subgraph Deduplication
J[Multiple useSWRSubscription with same key] --> B
B -->|shares subscription| A
end
style A fill:#f9f,stroke:#333,stroke-width:2px
style B fill:#bbf,stroke:#333,stroke-width:2px
style C fill:#bfb,stroke:#333,stroke-width:2px
style D fill:#ffe,stroke:#333,stroke-width:2px
Summary
This test file rigorously verifies the behavior, correctness, and robustness of the useSWRSubscription hook in various scenarios. It ensures the hook handles streaming data, errors, key updates, deduplication, and integrates cleanly with useSWR. It also confirms best practices such as requiring cleanup functions and proper error boundaries. The tests simulate realistic asynchronous behaviors and user interactions, providing confidence that useSWRSubscription can be safely used in production React applications.