Тест на принятие для расширения Markdown?

Привет!

Сейчас я работаю над расширением/плагином для Markdown, который добавляет довольно много тегов BBCode, и планирую написать для них acceptance-тесты в QUnit (мне надоело постоянно проверять их вручную, а их очень много).

Речь идёт о смеси простых тегов, которые просто оборачивают HTML, и сложных тегов, к которым привязаны обработчики событий. Поэтому мне нужно тестировать как итоговый HTML, так и работу обработчиков событий.

Я нашёл несколько примеров acceptance-тестов для расширений Markdown (а именно local-dates-composer-test.js.es6, spoiler-button-test.js-es6, checklist-test.js.es6 и pretty-text-test.js), которые использовал в качестве ориентиров. Эти тесты можно условно разделить на два подхода:

  1. Имитация открытия сайта, создания новой темы и ввода текста в редакторе, с последующим получением результата через селектор в DOM. (local-dates-composer-test.js.es6, spoiler-button-test.js-es6)
  2. Создание экземпляра Pretty Text для немедленной обработки текста и сравнение полученного HTML. (checklist-test.js.es6, pretty-text-test.js) (в тесте checklist также создаётся экземпляр модели Post для проверки обработчиков событий, и в целом кажется, что тестируется инициализатор).

Я попробовал оба метода и в целом добился успеха. Первый метод довольно прост, и я получил нужный результат, хотя это заняло больше времени, чем второй. Второй метод я также успешно реализовал, и тесты выполняются значительно быстрее, но при этом я получаю странную ошибку.

Вот мой код и результаты:

Метод 1: Имитация открытия сайта
import { acceptance, queryAll } from "discourse/tests/helpers/qunit-helpers";

QUnit.assert.cooked = async function (input, expected, message) {
  await fillIn(".d-editor-input", input);
  const actual = queryAll(".d-editor-preview")[0].innerHTML;
  this.pushResult({
    result: actual === expected.replace(/\/>/g, ">"),
    actual,
    expected,
    message,
  });
};

acceptance("Метод 1", function (needs) {
  needs.user();
  test("обработка через сайт", async function (assert) {
    await visit("/");
    await click("#create-topic");

    assert.cooked("hello world", "<p>hello world</p>", "этот тест работает");
  });
});

Метод 2: Создание экземпляра Pretty Text
import { acceptance} from "discourse/tests/helpers/qunit-helpers";
import { cookAsync } from "discourse/lib/text";

acceptance("Метод 2", function (needs) {
  needs.user();
  test("обработка с помощью cookAsync", async function (assert) {
    const cooked = await cookAsync("hello world", {});
    assert.equal(cooked, "<p>hello world</p>", "этот тест тоже работает");
  });
});

В данный момент оба метода просто проверяют простую обработку текста “hello world”. Я также протестировал их с моими собственными пользовательскими тегами, и они работают.

Кажется, для метода 2 чего-то не хватает, раз возникает ошибка afterEach failed ....: this.keyTrapper is null. В любом случае, оба метода работают, и я понимаю, что для простых проверок HTML следует использовать метод 2, а для тестов, затрагивающих обработчики событий, — метод 1.

Поскольку многие мои теги просто генерируют простой HTML, я хочу использовать метод 2 вместе с методом 1 в тестах, чтобы сэкономить время. Хотел бы узнать, чего именно мне не хватает, из-за чего возникает эта ошибка, или есть ли ещё более эффективный способ написания таких тестов в целом.

Вы можете посмотреть, как это реализовано в похожем официальном плагине

Но это не использование QUnit.

Дело в том, что, на мой взгляд, обработка происходит на бэкенде, между прочим.

Было бы здорово симулировать это на фронтенде.

Кстати, я лично перенёс плагин BBCode в компонент темы. Но не опубликовал его именно потому, что при этом теряются все тесты.