rdc-react-testing

📁 reactive/data-client 📅 Jan 31, 2026
3
总安装量
3
周安装量
#54804
全站排名
安装命令
npx skills add https://github.com/reactive/data-client --skill rdc-react-testing

Agent 安装分布

cursor 3

Skill 文档

Testing Patterns (@data-client/test)

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 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:

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

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)

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 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 directory: