Testing Patterns (@data-client/test)
SkillDev toolsLets your agent write and debug Jest tests for React hooks and components using the Data Client library.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Testing Patterns (@data-client/test) skill
About this capability
Test @data-client/react with renderDataHook and mountDataClient - jest unit tests, fixtures, interceptors, MockResolver, mock responses, nock HTTP mocking, fake timers for polling/subscription tests, DataProvider test setup, hook and component testing. Use when writing or debugging tests for hooks,
What this skill tells your AI
The instructions your AI receives, as published by reactive/data-client in .agents/skills/data-client-react-testing/SKILL.md and read by ahel’s review.
Hook Testing with renderDataHook()
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 storeresolverFixtures- Add interceptors for subsequent requestsgetInitialInterceptorData- Simulate changing server state
Return values:
- Inherits all
renderHook()return values from@testing-library/react controller- Controller instance for manual actionsallSettled()- Wait for all async operations to complete
Cleanup is automatic -- an afterEach hook is registered at module load time that drains all active cleanups. No manual renderDataHook.cleanup() calls are needed.
Fixtures and Interceptors
Success Fixture:
interface SuccessFixture {
endpoint;
args;
response;
error?;
delay?;
}
Response Interceptor:
interface ResponseInterceptor {
endpoint;
response(...args);
delay?;
delayCollapse?;
}
Testing Mutations
Create operations:
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
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
Use MockResolver to provide fixture data when rendering components with DataProvider:
import { render } from '@testing-library/react';
import { DataProvider } from '@data-client/react';
import { MockResolver } from '@data-client/test';
it('should render todo list', async () => {
const fixtures = [
{
endpoint: TodoResource.getList,
args: [],
response: [{ id: 1, title: 'Test Todo', completed: false }],
},
];
const { getByText } = render(
<DataProvider>
<MockResolver fixtures={fixtures}>
<TodoList />
</MockResolver>
</DataProvider>,
);
expect(getByText('Test Todo')).toBeInTheDocument();
});
Testing with nock (HTTP Endpoint Testing)
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
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
nockwhen 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
- Don't manually call
renderDataHook.cleanup()inafterEach-- cleanup is automatic
References
For detailed API documentation, see the references directory:
- renderDataHook - Hook testing utility
- makeRenderDataHook - Custom hook renderer
- Fixtures - Fixture format reference
- MockResolver - Component testing wrapper
- mockInitialState - Create initial state
- unit-testing-hooks - Hook testing guide
- unit-testing-components - Component testing guide
Signals
- GitHub stars
- 2k
- Forks
- 99
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
data-client-react-testing- Source
- github.com/reactive/data-client