home / skills / reactive / data-client / data-client-react-testing
This skill assists testing React data-client hooks and components with renderDataHook, fixtures, and nock HTTP mocks for reliable unit and integration tests.
npx playbooks add skill reactive/data-client --skill data-client-react-testingReview the files below or copy the command above to add this skill to your agents.
---
name: data-client-react-testing
description: Test @data-client/react with renderDataHook - jest unit tests, fixtures, interceptors, mock responses, nock HTTP mocking, hook testing, component testing
license: Apache 2.0
---
# Testing Patterns (@data-client/test)
## Hook Testing with renderDataHook()
```typescript
import { renderDataHook } from '@data-client/test';
it('useSuspense() should render the response', async () => {
const { result, waitFor } = renderDataHook(
() => useSuspense(ArticleResource.get, { id: 5 }),
{
initialFixtures: [
{
endpoint: ArticleResource.get,
args: [{ id: 5 }],
response: { id: 5, title: 'hi ho', content: 'whatever' },
},
],
},
);
expect(result.current.title).toBe('hi ho');
});
```
**Options:**
- `initialFixtures` - Set up initial state of the store
- `resolverFixtures` - Add interceptors for subsequent requests
- `getInitialInterceptorData` - Simulate changing server state
**Return values:**
- Inherits all `renderHook()` return values from `@testing-library/react`
- `controller` - Controller instance for manual actions
- `cleanup()` - Cleanup function
- `allSettled()` - Wait for all async operations to complete
## Fixtures and Interceptors
**Success Fixture:**
```typescript
interface SuccessFixture {
endpoint;
args;
response;
error?;
delay?;
}
```
**Response Interceptor:**
```typescript
interface ResponseInterceptor {
endpoint;
response(...args);
delay?;
delayCollapse?;
}
```
## Testing Mutations
**Create operations:**
```typescript
it('should create a new todo', async () => {
const { result } = renderDataHook(
() => useController(),
{
initialFixtures: [
{
endpoint: TodoResource.getList,
args: [],
response: [],
},
],
resolverFixtures: [
{
endpoint: TodoResource.getList.push,
response: (newTodo) => ({ ...newTodo, id: 1 }),
},
],
},
);
const newTodo = { title: 'Test Todo', completed: false };
const createdTodo = await result.current.fetch(TodoResource.getList.push, newTodo);
expect(createdTodo.id).toBe(1);
});
```
## Testing Error States
```typescript
it('should handle fetch errors', async () => {
const { result, waitFor } = renderDataHook(
() => useSuspense(TodoResource.get, { id: 1 }),
{
initialFixtures: [
{
endpoint: TodoResource.get,
args: [{ id: 1 }],
response: null,
error: new Error('Not found'),
},
],
},
);
await waitFor(() => {
expect(result.current).toBeUndefined();
});
});
```
## Testing Components
```typescript
import { render } from '@testing-library/react';
import { DataProvider } from '@data-client/react';
const renderWithProvider = (component, options = {}) => {
return render(
<DataProvider {...options}>
{component}
</DataProvider>
);
};
it('should render todo list', async () => {
const { getByText } = renderWithProvider(
<TodoList />,
{
initialFixtures: [
{
endpoint: TodoResource.getList,
args: [],
response: [{ id: 1, title: 'Test Todo', completed: false }],
},
],
},
);
expect(getByText('Test Todo')).toBeInTheDocument();
});
```
## Testing with nock (HTTP Endpoint Testing)
```typescript
import nock from 'nock';
it('should fetch data from API', async () => {
const scope = nock('https://jsonplaceholder.typicode.com')
.get('/todos/1')
.reply(200, { id: 1, title: 'Test', completed: false });
const result = await TodoResource.get({ id: 1 });
expect(result.title).toBe('Test');
scope.done();
});
```
## Testing Managers
```typescript
it('should handle manager middleware', async () => {
const mockManager = {
middleware: (controller) => (next) => async (action) => {
if (action.type === 'FETCH') {
console.log('Fetch action:', action);
}
return next(action);
},
cleanup: jest.fn(),
};
const { controller } = renderDataHook(
() => useController(),
{ managers: [mockManager] },
);
await controller.fetch(TodoResource.get, { id: 1 });
expect(mockManager.cleanup).not.toHaveBeenCalled();
});
```
## Test File Organization
**Keep tests under `packages/*/src/**/__tests__`:**
```
packages/react/src/hooks/__tests__/useSuspense.test.ts
packages/react/src/components/__tests__/DataProvider.test.tsx
```
**Test naming:**
- Node-only: `*.node.test.ts[x]`
- React Native: `*.native.test.ts[x]`
- Regular: `*.test.ts[x]`
## Best Practices
- Use `renderDataHook()` for testing hooks that use @data-client/react hooks
- Use fixtures or interceptors when testing hooks or components
- Use `nock` when testing networking definitions
- Test both success and error scenarios
- Test mutations and their side effects
- Don't mock @data-client internals directly
- Don't use raw fetch in tests when fixtures are available
## References
For detailed API documentation, see the [references](references/) directory:
- [renderDataHook](references/renderDataHook.md) - Hook testing utility
- [makeRenderDataHook](references/makeRenderDataHook.md) - Custom hook renderer
- [Fixtures](references/Fixtures.md) - Fixture format reference
- [MockResolver](references/MockResolver.md) - Component testing wrapper
- [mockInitialState](references/mockInitialState.md) - Create initial state
- [unit-testing-hooks](references/unit-testing-hooks.md) - Hook testing guide
- [unit-testing-components](references/unit-testing-components.md) - Component testing guide
This skill provides utilities and patterns for testing @data-client/react code with renderDataHook and related helpers. It focuses on Jest unit tests for hooks and components, offering fixture-driven state, interceptors, and optional HTTP mocking with nock. The goal is reliable, deterministic tests for REST/GraphQL/SSE hooks, mutations, and manager middleware.
Use renderDataHook to mount hooks that rely on @data-client/react and supply initialFixtures to populate store state synchronously. Add resolverFixtures to intercept subsequent requests and return mock responses or transforms. For full HTTP-level tests, use nock to stub network endpoints and assert request behavior. The renderer returns controller access, cleanup utilities, and wait helpers to coordinate async operations.
How do I simulate server-side state changes between requests?
Provide getInitialInterceptorData or resolverFixtures that compute responses based on prior calls to mimic evolving server state.
When should I use nock instead of fixtures?
Use nock when you want to exercise the actual HTTP layer or validate request shapes; use fixtures/resolvers for faster, isolated unit tests without network I/O.