Teste de Aceitação para Extensão Markdown?

Olá!

Atualmente estou trabalhando em uma extensão/plugin para Markdown que adiciona bastante tags BBCode, e estou procurando escrever testes de aceitação QUnit para eles (cansei de verificá-los manualmente constantemente, e são muitos).

As tags em questão são uma mistura entre tags simples que apenas aplicam HTML e tags complexas que possuem manipuladores de eventos anexados a elas. Assim, preciso testar tanto o HTML renderizado quanto os manipuladores de eventos.

Encontrei vários testes de aceitação para extensões de markdown (nomeadamente local-dates-composer-test.js.es6, spoiler-button-test.js-es6, checklist-test.js.es6, e pretty-text-test.js), que usei como referência. Estes podem ser amplamente separados em duas maneiras de realizar o teste:

  1. Simular a abertura do site, criar um novo tópico e preencher texto dentro do editor, obtendo a saída via um seletor no DOM. (local-dates-composer-test.js.es6, spoiler-button-test.js-es6)
  2. Criar uma instância do Pretty Text para renderizar o texto na hora e comparar o HTML lá. (checklist-test.js.es6, pretty-text-test.js) (o checklist parece também criar uma instância do modelo Post para testar o manuseio de eventos, e no geral parece estar testando o inicializador).

Tentei ambos os métodos e mais ou menos consegui. O primeiro método é bastante direto e consegui o que queria, mas ao custo de um tempo maior do que o segundo. No segundo método, consegui fazer com sucesso e com um tempo de teste muito mais rápido, mas estou recebendo um erro estranho.

Aqui estão meus códigos e resultados:

Método 1: Simular a abertura do site
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("Método 1", function (needs) {
  needs.user();
  test("renderização via site", async function (assert) {
    await visit("/");
    await click("#create-topic");

    assert.cooked("hello world", "<p>hello world</p>", "este teste funciona");
  });
});

Método 2: Criar uma Instância do Pretty Text
import { acceptance} from "discourse/tests/helpers/qunit-helpers";
import { cookAsync } from "discourse/lib/text";

acceptance("Método 2", function (needs) {
  needs.user();
  test("renderização usando cookAsync", async function (assert) {
    const cooked = await cookAsync("hello world", {});
    assert.equal(cooked, "<p>hello world</p>", "este teste também funciona");
  });
});

No momento, estou apenas testando uma renderização simples do texto “hello world”. Testei isso contra minhas próprias tags personalizadas e elas funcionam.

Acho que estou perdendo algo no método 2, já que o erro afterEach failed ....: this.keyTrapper is null aparece. De qualquer forma, ambos os métodos funcionam, e posso ver que para testes simples do HTML, devo usar o método 2 e para testes que envolverão manuseio de eventos, devo usar o método 1.

Como muitas das minhas tags são apenas HTML simples, quero usar o método 2 junto com o método 1 durante os testes, para economizar tempo. Gostaria de saber o que estou perdendo que está criando esse erro, ou se há uma maneira ainda melhor de escrever esses testes como um todo.

Você pode ver como é feito em um plugin oficial similar

Mas isso não está usando o QUnit.

A razão, creio eu, é que o processamento é feito no back-end, aliás.

Seria bom simular isso no front-end.

Aliás, migrei pessoalmente o plugin BBCode para um Componente de Tema, mas não o publiquei exatamente porque você perde todos os testes.