使用Jest测试MutationObserver

And*_*nna 13 jestjs

我写了一个脚本,其主要目的是为一些表格的单元格添加新元素.

测试是通过类似的方式完成的:

document.body.innerHTML = `
<body>
    <div id="${containerID}">
        <table>
            <tr id="meta-1"><td> </td></tr>
            <tr id="meta-2"><td> </td></tr>
            <tr id="meta-3"><td> </td></tr>
            <tr id="no-meta-1"><td> </td></tr>
        </table>
    </div>
</body>
`;

    const element = document.querySelector(`#${containerID}`);

    const subject = new WPMLCFInfoHelper(containerID);
    subject.addInfo();

    expect(mockWPMLCFInfoInit).toHaveBeenCalledTimes(3);
Run Code Online (Sandbox Code Playgroud)

mockWPMLCFInfoInit,当被调用时,告诉我该元素已添加到单元格中.

部分代码使用MutationObserver在mockWPMLCFInfoInit向表中添加新行时再次调用:

new MutationObserver((mutations) => {
    mutations.map((mutation) => {
        mutation.addedNodes && Array.from(mutation.addedNodes).filter((node) => {
            console.log('New row added');
            return node.tagName.toLowerCase() === 'tr';
        }).map((element) => WPMLCFInfoHelper.addInfo(element))
    });
}).observe(metasTable, {
    subtree:   true,
    childList: true
});
Run Code Online (Sandbox Code Playgroud)

WPMLCFInfoHelper.addInfo是真正的版本mockWPMLCFInfoInit(当然是一种模拟方法).

从上面的测试,如果添加这样的东西......

const table = element.querySelector(`table`);
var row = table.insertRow(0);
Run Code Online (Sandbox Code Playgroud)

console.log('New row added');永远不会被召唤.可以肯定的是,我也尝试在新行中添加所需的单元格.

当然,手动测试告诉我代码有效.

在我周围搜索,我的理解是不支持MutationObserver,并且没有计划支持它.

很公平,但在这种情况下,我如何测试我的代码的这一部分?除了手动,这是:)

sam*_*oul 19

我知道我在这里参加派对很晚,但在我的jest设置文件中,我只是添加了以下模拟MutationObserver类.

global.MutationObserver = class {
    constructor(callback) {}
    disconnect() {}
    observe(element, initObject) {}
};
Run Code Online (Sandbox Code Playgroud)

这显然不会让您测试观察者你想要做什么,但可以让你的代码的测试,其余的要运行的是通向一个有效的解决方案.

  • 请记住,这不会测试突变观察者的东西。我仍然没有找到一个好的解决方案,因此突变观察者在我的代码中的部分仍然令人恐惧。 (3认同)

Cod*_*ler 8

您可以使用mutationobserver-shim.

在 setup.js 中添加这个

import "mutationobserver-shim"
Run Code Online (Sandbox Code Playgroud)

并安装

npm i -D mutationobserver-shim
Run Code Online (Sandbox Code Playgroud)


Mat*_*att 7

我认为解决方案的相当一部分只是思维方式的转变。单元测试不应该确定是否MutationObserver正常工作。假设它是,并模拟您的代码利用的部分。

只需提取您的回调函数,即可独立测试;然后,模拟MutationObserver(如samuraiseoul 的回答)以防止错误。将模拟的MutationRecord列表传递给您的回调并测试结果是否符合预期。

这就是说,用玩笑的模拟功能,以嘲笑MutationObserverobserve()disconnect()方法至少会允许你检查的次数MutationObserver已创建以及是否方法已在预期时间被称为实例。

const mutationObserverMock = jest.fn(function MutationObserver(callback) {
    this.observe = jest.fn();
    this.disconnect = jest.fn();
    // Optionally add a trigger() method to manually trigger a change
    this.trigger = (mockedMutationsList) => {
        callback(mockedMutationsList, this);
    };
});
global.MutationObserver = mutationObserverMock;

it('your test case', () => {
    // after new MutationObserver() is called in your code
    expect(mutationObserverMock.mock.instances).toBe(1);

    const [observerInstance] = mutationObserverMock.mock.instances;
    expect(observerInstance.observe).toHaveBeenCalledTimes(1);
});

Run Code Online (Sandbox Code Playgroud)


Pur*_*lex 5

由于JSm不支持MutationObserver,实际上出现了问题,因此您必须提供适当的polyfill

有点棘手的想法可能不是最佳解决方案(让我们使用库旨在与IE9-10兼容)。

步骤1(将此库安装到devDependencies)

npm install --save-dev mutation-observer
Run Code Online (Sandbox Code Playgroud)

第2步(导入并设为全局)

import MutationObserver from 'mutation-observer'
global.MutationObserver = MutationObserver 

test('your test case', () => { 
   ...
})
Run Code Online (Sandbox Code Playgroud)