你好!
我目前正在开发一个 Markdown 扩展/插件,它会添加大量的 BBCode 标签。为了测试这些标签,我打算编写 QUnit 验收测试(因为手动反复检查实在太累了,而且标签数量众多)。
这些标签既包含仅应用 HTML 的简单标签,也包含附加了事件处理程序的复杂标签。因此,我需要同时测试渲染后的 HTML 内容以及事件处理程序。
我查阅了许多 Markdown 扩展的验收测试案例(特别是 local-dates-composer-test.js.es6、spoiler-button-test.js-es6、checklist-test.js.es6 以及 pretty-text-test.js),并以此作为参考。这些测试大致可以分为两类方法:
- 模拟打开网站、创建新主题,并在编辑器中输入文本,然后通过 DOM 选择器获取输出结果。(参考:local-dates-composer-test.js.es6、spoiler-button-test.js-es6)
- 创建 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("Method 1", function (needs) {
needs.user();
test("cooking via site", async function (assert) {
await visit("/");
await click("#create-topic");
assert.cooked("hello world", "<p>hello world</p>", "this test works");
});
});
方法 2:创建 Pretty Text 实例
import { acceptance} from "discourse/tests/helpers/qunit-helpers";
import { cookAsync } from "discourse/lib/text";
acceptance("Method 2", function (needs) {
needs.user();
test("cooking using cookAsync", async function (assert) {
const cooked = await cookAsync("hello world", {});
assert.equal(cooked, "<p>hello world</p>", "this test also works");
});
});
目前,我的测试仅针对简单的文本 “hello world” 进行渲染。我也用我自己的自定义标签测试过,它们确实能正常工作。
我觉得方法 2 中我可能遗漏了什么,因为报错信息显示 afterEach failed ....: this.keyTrapper is null。不过,无论如何,两种方法都能运行。我可以看到,对于简单的 HTML 测试,应该使用方法 2;而对于涉及事件处理的测试,则应使用方法 1。
由于我的许多标签只是简单的 HTML,为了节省时间,我想在测试中同时使用方法 2 和方法 1。我想知道是什么导致了那个错误,或者是否有更好的方式来编写这些测试。

