Skip to content

Testing ​

React parts are tested with Jest and Testing Library, run npm test.

Setup (already in the repo):

FilePurpose
jest.config.cjsjsdom environment, moduleNameMapper for Components/*, setupTests.js. It is .cjs because package.json has "type": "module"
.babelrc@babel/preset-env + @babel/preset-react for test files
setupTests.jsjest-dom matchers, global React, stubs for Drupal.t and drupalSettings, matchMedia

Example ​

Components rely on globals that Drupal provides (Drupal, apiClient), so stub them in beforeEach:

jsx
import { RecipeExplorer } from '../RecipeExplorer';
import { render, screen, waitFor, fireEvent } from '@testing-library/react';

beforeEach(() => {
  window.Drupal = {
    t: (s, args = {}) => Object.entries(args).reduce((r, [k, v]) => r.replace(k, v), s),
    formatPlural: (n, one, many) => (n === 1 ? one : many.replace('@count', n)),
  };
  window.apiClient = jest.fn(() => Promise.resolve(response([recipe])));
  global.apiClient = window.apiClient;
});

it('requests the endpoint again when a filter changes', async () => {
  render(<RecipeExplorer endpoint="/api/recipes" heading="Recipes" />);
  await screen.findByText('Soup');
  fireEvent.change(screen.getByLabelText('Difficulty'), { target: { value: 'hard' } });
  await waitFor(() => expect(apiClient).toHaveBeenLastCalledWith('/api/recipes', { difficulty: 'hard' }));
});

Test the React component (RecipeExplorer.jsx), not index.jsx: the behavior wrapper only wires Drupal to React.

What is not covered ​

  • Drupal-side rendering (SDC props validation, library attachment) needs a running site or core's ComponentKernelTestBase.
  • The demo recorder (npm run demo) doubles as a smoke test: it fails with exit code 1 if the browser logs a console error or page error.