Unit тестирование MDX компонентов

MDX (Markdown for JSX) позволяет объединять разметку Markdown и React-компоненты в одном файле. Тестирование таких компонентов требует понимания того, как JSX интегрирован с Markdown, и как правильно изолировать компонент для unit-тестирования.

Структура MDX-компонента

MDX-файл обычно состоит из трёх частей:

  1. Импорты компонентов

    import { Button } from './Button';
  2. Markdown-разметка

    # Заголовок
    Здесь используется компонент:
    <Button>Click me</Button>
  3. Встраивание React-компонентов Любой JSX-код может быть вставлен напрямую в MDX-файл, что делает тестирование сложнее, чем обычного React-компонента, поскольку Markdown-контент должен быть корректно обработан.

Выбор инструментов для unit-тестирования

Для MDX-компонентов подходят стандартные инструменты React-тестирования:

  • Jest — тест-раннер для запуска unit-тестов.
  • React Testing Library (RTL) — для рендеринга компонентов и проверки их DOM-структуры.
  • @mdx-js/react — для корректного рендеринга MDX-файлов в тестовой среде.

Пример установки:

npm install --save-dev jest @testing-library/react @testing-library/jest-dom @mdx-js/react

Настройка окружения

MDX-файлы не могут быть импортированы напрямую в Jest без обработки. Используется транспайлер или мок-файлы.

  1. Настройка Babel для MDX:

    {
      "presets": ["@babel/preset-env", "@babel/preset-react"],
      "plugins": ["@babel/plugin-transform-react-jsx"]
    }
  2. Мок MDX для Jest: В jest.config.js можно добавить:

    moduleNameMapper: {
      "\\.mdx$": "<rootDir>/__mocks__/mdxMock.js"
    }

    Где mdxMock.js экспортирует React-компонент-заглушку:

    import React from 'react';
    export default ({ children }) => <div>{children}</div>;

Рендеринг MDX-компонента в тестах

MDX требует обёртки через MDXProvider из @mdx-js/react для корректной интерпретации JSX внутри Markdown. Пример:

import { render, screen } from '@testing-library/react';
import { MDXProvider } from '@mdx-js/react';
import MyMDXComponent from './MyComponent.mdx';

test('рендерит заголовок и кнопку', () => {
  render(
    <MDXProvider>
      <MyMDXComponent />
    </MDXProvider>
  );

  expect(screen.getByText('Заголовок')).toBeInTheDocument();
  expect(screen.getByText('Click me')).toBeInTheDocument();
});

Проверка интерактивных элементов

Для кнопок, форм и других интерактивных компонентов используется fireEvent или userEvent из @testing-library/user-event:

import userEvent from '@testing-library/user-event';

test('кнопка реагирует на клик', async () => {
  render(
    <MDXProvider>
      <MyMDXComponent />
    </MDXProvider>
  );

  const button = screen.getByText('Click me');
  await userEvent.click(button);
  expect(screen.getByText('Clicked')).toBeInTheDocument();
});

Изоляция MDX-компонентов

Unit-тестирование предполагает проверку отдельного компонента без побочных эффектов. Для MDX это важно, поскольку Markdown-контент может содержать сложные вставки:

  • Разделять MDX на меньшие компоненты.
  • Тестировать JSX внутри MDX отдельно.
  • Использовать мок-компоненты для тяжелых зависимостей.

Снимки (Snapshot Testing)

Для статичных MDX-файлов удобно использовать snapshot-тесты:

import { render } from '@testing-library/react';
import { MDXProvider } from '@mdx-js/react';
import MyMDXComponent from './MyComponent.mdx';

test('snapshot MDX компонента', () => {
  const { container } = render(
    <MDXProvider>
      <MyMDXComponent />
    </MDXProvider>
  );
  expect(container).toMatchSnapshot();
});

Snapshot-тесты фиксируют текущую структуру DOM, что полезно для проверки изменений Markdown-разметки и встроенных компонентов.

Типичные ошибки при тестировании MDX

  • Попытка рендерить MDX без MDXProvider — приводит к ошибкам интерпретации JSX.
  • Игнорирование интерактивных элементов — тест становится неполным.
  • Прямая проверка текста без учёта Markdown-разметки — может пропустить теги и вложенные компоненты.
  • Не использование моков для зависимостей — тест может сломаться из-за сложных импортов или нестабильных данных.

Стратегии эффективного тестирования

  1. Тестировать функциональные компоненты отдельно до интеграции с MDX.
  2. Тестировать MDX как интеграцию Markdown и компонентов через MDXProvider.
  3. Комбинировать unit и snapshot-тесты — unit-тесты для логики, snapshot для разметки.
  4. Использовать пользовательские события для проверки интерактивности.

Такой подход позволяет покрыть как статические элементы Markdown, так и динамические React-компоненты внутри MDX-файлов, обеспечивая надёжность и стабильность интерфейса.