use-swr-focus.test.tsx
Overview
This file contains a suite of automated tests designed to verify the behavior of the useSWR React hook with respect to focus-based revalidation. The tests validate how useSWR handles data fetching when the browser window regains focus under different configuration options such as revalidateOnFocus and focusThrottleInterval.
useSWR is a popular React hook for data fetching that supports revalidation strategies to keep data fresh. The focus-related revalidation behavior ensures that when a user returns to a tab or window, the latest data is fetched automatically unless explicitly disabled or throttled.
Key testing aspects covered in this file include:
Default revalidation behavior on window focus
Disabling revalidation on focus
Reactivity of
revalidateOnFocusandfocusThrottleIntervaloptions when changed dynamically (stateful behavior)Throttling of focus-triggered revalidations to avoid excessive fetches
Interaction with custom cache implementations
Edge cases where the key changes rapidly within the same event tick
The tests are implemented with React Testing Library and Jest, using utilities to simulate focus events and control asynchronous timing.
Detailed Explanation of Components and Functions
Imported Utilities
act,fireEvent,screenfrom@testing-library/react: Used for simulating user interactions, DOM events, and managing React's state update lifecycle in tests.useState from
react: Used in test components to dynamically toggle options.useSWRfromswr: The hook under test.Custom utilities from
'./utils':sleep(ms): Delays execution bymsmilliseconds.nextTick(aliased aswaitForNextTick): Waits until the next event loop tick, used to wait for async updates.focusOn(element): Programmatically triggers a focus event on the specified element.renderWithConfig(component): Renders React components within a specific test configuration/environment.createKey(): Generates unique keys for SWR cache identification.
focusWindow()
const focusWindow = () => focusOn(window)
Helper function that triggers a focus event on the global window object, simulating a user returning focus to the browser tab. This is the main trigger for SWR's focus revalidation logic in tests.
Test Suite: 'useSWR - focus'
The test suite groups tests verifying SWR's focus revalidation behavior.
Test: 'should revalidate on focus by default'
Purpose: Verify that SWR automatically revalidates data when window focus occurs (default behavior).
Implementation:
A dummy fetcher increments a
valueon each fetch.The SWR hook uses
dedupingInterval: 0andfocusThrottleInterval: 0to disable deduplication and throttling.After initial render and hydration, triggering a focus event causes the data to update from
0to1.
Usage example:
const { data } = useSWR(key, () => value++, {
dedupingInterval: 0,
focusThrottleInterval: 0
})
Test: "shouldn't revalidate on focus when revalidateOnFocus is false"
Purpose: Confirm that setting
revalidateOnFocus: falsedisables revalidation on window focus.Implementation: Similar to above but with
revalidateOnFocus: false. Focus events do not trigger data updates.Key point: This option disables focus-triggered fetches regardless of other config.
Test: 'revalidateOnFocus should be stateful'
Purpose: Test that toggling
revalidateOnFocusdynamically (via React state) affects whether revalidation happens on focus.Implementation:
revalidateOnFocusis stored in component state and toggled by clicking the displayed data.When
false, focus does not trigger revalidation.When toggled to
true, focus triggers revalidation and updates data.Toggled back to
falsedisables revalidation again.
Key insight: SWR respects dynamic changes to focus revalidation config.
Test: 'focusThrottleInterval should work'
Purpose: Verify the throttling behavior that prevents revalidation from happening too frequently on focus.
Implementation:
focusThrottleIntervalis set to 50 milliseconds.Multiple focus events within 50ms only trigger a single revalidation.
After waiting longer than throttle interval, focus triggers revalidation again.
Significance: Prevents excessive network requests on rapid focus changes.
Test: 'focusThrottleInterval should be stateful'
Purpose: Validate that the throttle interval can be dynamically updated.
Implementation:
focusThrottleIntervalis stored in state and increased by clicking the displayed data.The test exercises multiple focus events with changing throttle intervals.
Demonstrates: SWR responds to dynamic throttle interval changes.
Test: 'should revalidate on focus even with custom cache'
Purpose: Ensure focus revalidation works correctly when using a custom SWR cache.
Implementation: Similar to the default test but assumes usage of a custom cache (implied by
renderWithConfig).Importance: Confirms compatibility with advanced SWR configurations.
Test: 'should not revalidate on focus when key changes in the same tick'
Purpose: Handle the edge case where the SWR key changes immediately after focus, avoiding duplicate or unnecessary fetches.
Implementation:
The component maintains a key in state, which can be changed on click.
Focus and key change events happen in the same event loop tick.
The fetcher logs keys fetched to verify only expected fetches occur.
Outcome: Only two fetches happen: one for the initial key, one for the new key, demonstrating correct deduplication logic.
Important Implementation Details and Algorithms
Focus revalidation logic in
useSWR: When the window regains focus, SWR triggers a re-fetch of the data unless:revalidateOnFocusis set tofalse.The last focus-triggered revalidation happened within the configured
focusThrottleInterval.
Throttling Algorithm: SWR tracks the timestamp of the last focus revalidation and rejects subsequent revalidations triggered within the throttle interval.
Stateful Config Options: Both
revalidateOnFocusandfocusThrottleIntervalcan be updated dynamically via React state, and SWR respects these changes immediately.Key change deduplication: If the key changes in the same tick as a focus event, SWR avoids redundant revalidation by carefully deduplicating fetches.
Interaction With Other Parts of the System
useSWRhook: This file tests a specific behavior of the SWR hook related to focus events../utilsmodule: Provides essential helpers for testing such as simulating focus events (focusOn), advancing event loop ticks (nextTick), sleeping/delays (sleep), rendering SWR components in a test environment (renderWithConfig), and generating unique keys (createKey).React Testing Library: Used for rendering components and simulating user interactions.
Browser Window Focus Events: The tests simulate
windowfocus events to trigger SWR's revalidation mechanism.Custom Cache: Some tests imply SWR's ability to work with custom caches, which might be configured in
renderWithConfigor elsewhere in the test environment.
Usage Examples
Basic focus revalidation
const { data } = useSWR('my-key', fetcher, { dedupingInterval: 0 })
// When window regains focus, SWR refetches data automatically.
Disable focus revalidation
const { data } = useSWR('my-key', fetcher, { revalidateOnFocus: false })
// Window focus does not trigger data refetch.
Throttle focus revalidation
const { data } = useSWR('my-key', fetcher, {
revalidateOnFocus: true,
focusThrottleInterval: 100 // ms
})
// Revalidation on focus is throttled to once per 100ms.
Visual Diagram: Component & Function Flow in Tests
The file tests multiple React components (Page) with different configurations of the useSWR hook. The flowchart below represents the core interactions between the test functions, components, and utilities used to simulate focus and validate results.
flowchart TD
A[Test Suite: 'useSWR - focus'] --> B[Individual Test Cases]
B --> C[Page Component with useSWR]
C -->|calls| D[useSWR Hook]
D -->|fetches| E[Fetcher Function (increments value)]
B --> F[renderWithConfig]
B --> G[focusWindow triggers focusOn(window)]
G --> H[window focus event triggers SWR revalidation]
H --> D
B --> I[fireEvent (click, focus)]
B --> J[Assertions (screen.getByText, findByText)]
F --> C
I --> C
J --> B
The test suite contains multiple tests that render a
Pagecomponent.The
Pagecomponent usesuseSWRwith different options.Focus events on
windowtrigger SWR revalidation flows depending on configuration.User interactions (clicks) update stateful configs like
revalidateOnFocusandfocusThrottleInterval.Assertions verify UI updates reflecting data changes.
Summary
The use-swr-focus.test.tsx file is a comprehensive test suite validating the nuanced behavior of the useSWR hook in relation to window focus events and how it controls data revalidation. It confirms default behaviors, configuration options, dynamic changes, throttling, and edge cases to ensure robust and expected data fetching behaviors in React applications using SWR. The file relies on utilities to simulate asynchronous events and user interactions effectively.
This test suite is crucial for guaranteeing the reliability of UI data freshness triggered by user focus changes, which is a common real-world scenario in SPA (Single Page Application) environments.