Snapshot тестирование результатов

Snapshot тестирование позволяет зафиксировать текущее состояние обработки Markdown или HTML и выявлять изменения в будущем. В экосистеме Remark и Rehype это особенно полезно для проверки конверсий Markdown → AST → HTML, а также любых трансформаций, применяемых к документу.


Создание AST с помощью Remark

Remark преобразует Markdown в MDAST (Markdown Abstract Syntax Tree). Этот AST представляет собой объектную структуру, где каждая нода описывает элемент документа:

import { remark } from 'remark';

const markdown = '# Заголовок 1\n\nТекст параграфа.';
const ast = remark().parse(markdown);

console.log(JSON.stringify(ast, null, 2));

Ключевые свойства MDAST:

  • type — тип узла (root, paragraph, heading, text и т.д.).
  • children — массив дочерних узлов.
  • value — текстовое содержимое (для текстовых узлов).

Snapshot тестирование может фиксировать AST, что позволяет контролировать корректность парсинга Markdown.


Преобразование AST в HTML через Rehype

Rehype работает с HAST (HTML AST). Remark можно интегрировать с Rehype, чтобы конвертировать Markdown → HTML через AST.

Пример:

import { remark } from 'remark';
import remarkRehype from 'remark-rehype';
import rehypeStringify from 'rehype-stringify';

const markdown = '# Заголовок 1\n\nПараграф текста.';
const processor = remark()
  .use(remarkRehype)
  .use(rehypeStringify);

const html = await processor.process(markdown);
console.log(String(html));

Особенности HAST:

  • type — узлы могут быть element, text, comment.
  • tagName — имя HTML-тега (h1, p, ul).
  • properties — атрибуты HTML-элемента.
  • children — дочерние узлы, аналогично MDAST.

Snapshot тестирование HAST позволяет фиксировать результат преобразования Markdown в HTML до и после применения плагинов или изменений кода.


Организация snapshot тестов

Для фиксации AST или HTML используют тестовые фреймворки с поддержкой снапшотов, например Jest. Пример теста:

import { remark } from 'remark';
import remarkRehype from 'remark-rehype';
import rehypeStringify from 'rehype-stringify';

test('Markdown конвертируется корректно', async () => {
  const markdown = '# Заголовок\n\nПараграф текста.';
  
  const processor = remark().use(remarkRehype).use(rehypeStringify);
  const result = await processor.process(markdown);

  expect(String(result)).toMatchSnapshot();
});

Преимущества snapshot тестирования:

  • Автоматическое выявление непреднамеренных изменений.
  • Возможность проверки больших документов без ручного анализа HTML.
  • Контроль корректности работы плагинов Remark/Rehype.

Snapshot для плагинов Remark

Remark поддерживает расширение через плагины для добавления функционала: обработка ссылок, таблиц, кастомные синтаксические конструкции. Снапшоты позволяют тестировать работу этих плагинов:

import remarkEmoji from 'remark-emoji';

test('Эмодзи преобразуются корректно', async () => {
  const markdown = 'Привет :smile:';
  const ast = await remark().use(remarkEmoji).parse(markdown);

  expect(ast).toMatchSnapshot();
});

Фиксация AST гарантирует, что плагин не нарушает структуру документа.


Snapshot для Rehype-плагинов

Rehype-плагины работают на HAST, добавляя атрибуты, классы или изменяя структуру HTML. Снапшоты фиксируют результат:

import rehypeAddClasses from 'rehype-add-classes';
import { remark } from 'remark';
import remarkRehype from 'remark-rehype';
import rehypeStringify from 'rehype-stringify';

test('Классы добавляются к элементам', async () => {
  const markdown = '### Подзаголовок';
  const html = await remark()
    .use(remarkRehype)
    .use(rehypeAddClasses, { 'h3': 'heading-class' })
    .use(rehypeStringify)
    .process(markdown);

  expect(String(html)).toMatchSnapshot();
});

Снапшоты позволяют сразу увидеть, добавился ли класс к h3 и не были ли повреждены другие элементы.


Рекомендации по организации снапшотов

  • AST и HAST в JSON: сохранять в виде структурированных JSON для удобного анализа.
  • Разделение по типам документов: тестировать разные виды контента отдельно.
  • Версионирование: при изменении плагинов или библиотек обновлять снапшоты сознательно, а не автоматически.

Практические советы

  1. Фиксировать только важные изменения: избегать снапшотов слишком больших документов без разбивки на части.
  2. Использовать pretty-format для JSON: делает снапшоты читаемыми.
  3. Тестировать плагин по отдельности и в связке: сначала убедиться, что плагин работает корректно на AST, затем проверить HTML.
  4. Сравнивать Markdown → HTML → снапшот: помогает обнаруживать скрытые баги при интеграции Remark и Rehype.

Snapshot тестирование в связке Remark и Rehype становится инструментом не только для контроля изменений, но и для документирования структуры контента и поведения плагинов.