use-swr-remote-mutation.test.tsx
Overview
This file contains a comprehensive suite of unit and integration tests for verifying the behavior of the useSWRMutation hook, a React hook from the SWR (stale-while-revalidate) library ecosystem. The useSWRMutation hook allows performing remote mutations (e.g., POST, PUT, DELETE requests) and optionally updating the SWR cache to reflect the mutation results.
The tests validate various aspects of useSWRMutation including:
Basic triggering and data return
Argument passing to mutation functions
Success and error callbacks
State flags such as
isMutatingCache population and sharing with
useSWRRace condition prevention
Revalidation behavior after mutation
Optimistic updates
Resetting state
Handling of missing mutators or invalid keys
Usage of the latest fetcher and config
These tests simulate UI interactions (e.g., clicking buttons) to trigger mutations and use assertions to check expected UI states, function calls, and cache updates. This ensures that useSWRMutation behaves correctly and integrates seamlessly with useSWR.
Detailed Explanations
Imports and Utilities
act,fireEvent,render, screen from@testing-library/react: Used for rendering React components and simulating user interactions in tests.React, { useState } fromreact: Core React library and hooks.useSWRfromswr: The primary SWR data fetching hook.useSWRMutationfromswr/mutation: The hook under test for performing remote mutations.Utility functions imported from
'./utils':createKey(): Generates unique keys for SWR cache.sleep(ms): Returns a promise that resolves aftermsmilliseconds (used to simulate asynchronous delays).nextTick(): Advances to the next event loop tick.createResponse(value): Wraps a value in a response object for testing.
waitForNextTick: A helper function that wrapsactand sleep(1) to wait for React updates and promises to resolve.
Test Suite: 'useSWR - remote mutation'
The test suite is organized into many individual it tests. Each test mounts a small React component that uses useSWRMutation (and sometimes useSWR), simulates user events, and asserts expected outcomes.
Key Tests and Their Explanations
1. Basic triggering and returning data
const { data, trigger } = useSWRMutation(key, () => 'data')
Renders a button showing "pending" initially.
On click,
trigger()is called which runs the mutation function returning'data'.Verifies button text updates to
'data'.
Usage example:
function Page() {
const { data, trigger } = useSWRMutation('key', () => 'data');
return <button onClick={() => trigger()}>{data || 'pending'}</button>;
}
2. Returning data from the trigger function
Stores mutation result in local state via
await trigger().Shows how the
triggermethod returns the mutation result promise.
3. Verifying argument passing to mutation function
Passes an array key
[key, 'arg0'].Mutation function is a Jest mock
fetcherthat expects arguments(_, { arg }).Calls
trigger('arg1')and verifiesfetchercalled with expected args.
4. onSuccess callback
Provides an
onSuccesscallback in theuseSWRMutationconfig.Asserts it is called after successful mutation.
5. Configurable onSuccess per trigger
Passes
onSuccesscallback as an option totrigger()call.Verifies that it overrides or supplements hook-level config.
6. Error handling with onError and throwing
Mutation function throws an error after delay.
onErrorand in-place.catch()handlers are asserted to be called.Verifies error message shown in UI.
7. throwOnError: false disables throwing on error
Similar to above but with
throwOnError: false.Verifies no error is thrown to caller.
8. isMutating state flag
Shows
isMutatingistrueduring mutation andfalseafter resolving.
9. Sharing cache with useSWR via populateCache
Runs a mutation and populates the SWR cache.
useSWRhook reading the same key reflects updated data.
10. Preventing race conditions
Tests that outdated data from previous mutations or SWR fetches never override latest state.
11. Optimistic updates support
Demonstrates using
optimisticDataand custompopulateCacheduring mutation.UI updates immediately with optimistic data, then updates with resolved data.
12. Resetting mutation state
Demonstrates calling
reset()clears data and error states.
13. Using the latest fetcher and config
Shows that mutation uses the most recent version of fetcher function and config callbacks, even if they change between renders.
14. Handling empty or missing keys
Triggering mutation with a null or missing key throws an error.
Using
nullkey disables mutation.
Important Implementation Details / Algorithms
The tests simulate real asynchronous network behavior using
sleepandactto ensure React state updates and promise resolutions are processed correctly.useSWRMutationreturns an object with:data: mutation resulterror: error object if mutation failedisMutating: boolean loading flagtrigger: function to invoke mutationreset: function to reset mutation state
The
triggerfunction accepts:Optional argument to be passed to the mutation function.
Options object supporting:
onSuccess,onError: per-trigger callbackspopulateCache: boolean or function to update SWR cache with mutation resultrevalidate: boolean or function to control revalidation behaviorthrowOnError: boolean to control error throwing behavioroptimisticData: data or updater function for optimistic UI updates
Interaction with Other Parts of the System
useSWRMutationintegrates tightly with the coreuseSWRhook by sharing the same cache key and cache storage.Mutations can populate the shared cache, causing
useSWRhooks to update automatically.Revalidation after mutation triggers SWR data fetching to keep data fresh.
The tests use utilities like
createKey()and helpers likesleep()from the local'./utils'module.This test suite ensures that the mutation hook respects the SWR lifecycle and cache management semantics.
Example Usage
import useSWR from 'swr'
import useSWRMutation from 'swr/mutation'
function Profile() {
const { data: profile } = useSWR('/api/profile')
const { trigger, isMutating } = useSWRMutation('/api/profile', updateProfile)
async function updateProfile(newData) {
const res = await fetch('/api/profile', {
method: 'POST',
body: JSON.stringify(newData),
})
return res.json()
}
return (
<div>
<pre>{JSON.stringify(profile)}</pre>
<button onClick={() => trigger({ name: 'New Name' })} disabled={isMutating}>
Update Profile
</button>
</div>
)
}
Mermaid Diagram
This file is a test file composed of multiple independent React components used to test the useSWRMutation hook. Below is a flowchart illustrating the main functions and their relationships within this test file:
flowchart TD
A[useSWRMutation hook] --> B[trigger() function]
B --> C[mutation function (fetcher)]
B --> D[onSuccess callback]
B --> E[onError callback]
B --> F[populateCache option]
B --> G[revalidate option]
A --> H[isMutating state]
A --> I[data state]
A --> J[error state]
A --> K[reset() function]
subgraph Tests
L[Basic triggering and data return]
M[Argument passing to mutator]
N[Success and error callbacks]
O[Cache population with useSWR]
P[Race condition prevention]
Q[Optimistic updates]
R[Resetting state]
S[Latest fetcher and config usage]
end
L --> A
M --> A
N --> A
O --> A & useSWR
P --> A & useSWR
Q --> A & useSWR
R --> A
S --> A
Summary
The file use-swr-remote-mutation.test.tsx is a test suite for the
useSWRMutationReact hook.It verifies the correctness of mutation triggering, argument passing, error/success handling, cache integration, and state management.
It simulates UI interactions and asynchronous behaviors to ensure reliable hook behavior.
It demonstrates advanced usage scenarios such as optimistic updates and race condition handling.
The tests ensure
useSWRMutationworks seamlessly withuseSWRand respects SWR's caching and revalidation workflows.
This file is essential for maintaining the quality and reliability of the remote mutation feature in the SWR ecosystem.