Snapshot тестирование позволяет зафиксировать текущее состояние обработки Markdown или HTML и выявлять изменения в будущем. В экосистеме Remark и Rehype это особенно полезно для проверки конверсий Markdown → AST → HTML, а также любых трансформаций, применяемых к документу.
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.
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 до и после применения плагинов или изменений кода.
Для фиксации 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 тестирования:
Remark поддерживает расширение через плагины для добавления функционала: обработка ссылок, таблиц, кастомные синтаксические конструкции. Снапшоты позволяют тестировать работу этих плагинов:
import remarkEmoji from 'remark-emoji';
test('Эмодзи преобразуются корректно', async () => {
const markdown = 'Привет :smile:';
const ast = await remark().use(remarkEmoji).parse(markdown);
expect(ast).toMatchSnapshot();
});
Фиксация AST гарантирует, что плагин не нарушает структуру документа.
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 и не были ли повреждены другие элементы.
pretty-format для JSON:
делает снапшоты читаемыми.Snapshot тестирование в связке Remark и Rehype становится инструментом не только для контроля изменений, но и для документирования структуры контента и поведения плагинов.