模拟单击文档ReactJS / JSDom

时间:2014-12-18 23:36:55

标签: javascript unit-testing reactjs jsdom

所以我正在编写一些代码,用于在文档上添加click事件。我正在使用JSDom,ReactJS和Mocha / Chai设置。我在测试中尝试了以下代码:

document.addEventListener('click', function() {
  console.log('test');
});
React.addons.TestUtils.Simulate.click(document);
//also tried React.addons.TestUtils.Simulate.click(document.body);

但是这段代码不会产生我期待的回声。

有没有办法用JSDom和ReactJS模拟文档上的click,keyup等?

更新

对尼克回答,我尝试将此代码添加到测试中:

document.body.addEventListener('click', function() {
  console.log('test');
});

document.body.click();

我直到没有得到控制台日志输出。我不确定JSDom是否存在某些问题以及做这类事情。

如果我无法对这段代码进行单元测试,那很好,已经有一些我现在无法进行单元测试的代码(代码需要一个真正的DOM才能获得宽度,高度等等...... )但我希望能够对大部分代码进行单元测试(我对使用PhantomJS进行单元测试不感兴趣)。我的集成测试将涵盖这种类型的代码。

UPDATE2

需要注意的另一件事是,当我console.log(document);时,我看到对象附加到_listeners的{​​{1}}属性,所以我知道事件是附加的,它似乎不是正在执行。

5 个答案:

答案 0 :(得分:27)

更新: document.body.click可在浏览器中使用,但对于jsdom,您需要手动创建事件:

document.body.addEventListener('click', function() {
  console.log('test');
});

var evt = document.createEvent("HTMLEvents");
evt.initEvent("click", false, true);
document.body.dispatchEvent(evt)

以上代码在Jest中为我工作,也应该与“solo”jsdom合作。

2018年秋季假期更新

围绕模拟事件的工具已经变得更好了。我目前已经改变了方法,使用优秀的react-testing-library来渲染我的组件并发送事件:

import {render, fireEvent} from 'react-testing-library'

test('example', () => {
  const handleClick = jest.fn()

  const {getByText} = render(<div><button onClick={handleClick}>Click Me</button></div>)
  fireEvent.click(getByText('Click Me'))

  expect(handleClick).toHaveBeenCalled()
})

虽然我仍然相信使用像puppeteer或selenium(或cypress!)这样的端到端测试,但它可以提供最高级别的信任,实际上可以正常工作,这可以提供巨大的价值,而不会通过手动事件创建来污染测试。 / p>

答案 1 :(得分:6)

React.addons.TestUtils.Simulate仅适用于虚拟事件。如果要分发本机事件,可以直接使用DOM api执行此操作。

模拟点击时,如果你有一个组件可以渲染:

<div>
   <button onClick={alert}>click me</button>
</div>

您可以在名为&#39; buttonEl&#39;的变量中引用<button/>,然后运行:

React.addons.TestUtils.Simulate.click(buttonEl, 'hello world');

您可以通过“hello world&#39;在里面。所有测试工具都会创建虚拟事件,让它冒泡虚拟dom树,沿途调用事件处理程序。

答案 2 :(得分:1)

您可以使用 Simulate => react-dom/test-utils 中的 Simulate.click(your_button) 函数

这是我使用的示例 mochachaijsdom


import ReactDOM from "react-dom";
import {act, Simulate} from "react-dom/test-utils";
import {assert} from 'chai';
import {Folder} from "../components/Folder"

let rootContainer:any;

// Define the code that will run before and after the test
beforeEach(() => {
  rootContainer = window.document.createElement("div");
  window.document.body.appendChild(rootContainer);
});

afterEach(() => {
  window.document.body.removeChild(rootContainer);
  rootContainer = null;
});

describe('Folder', ()=>{
  
    // an empty folder
    const empty_folder = {
        "name": "Music",
        "items": []
    };


    // test that the file render automatically
    it("Renders should render a Folder", () => {
        act(() => {
            ReactDOM.render(<Folder folder_obj={empty_folder} level = {0}/> , rootContainer);
        });
        // Get the html elements of Folder components
        const folder_wrapper = rootContainer.querySelector(".wrapper");
        const foldername_span = rootContainer.querySelector(".left-part span:last-child");
        const foldericon = rootContainer.querySelector(".left-part span:first-child i");
        const folderitems_span = rootContainer.querySelector(".right-part span");

        // Check if the folder name, icons, number of items are rendred correctly
        assert.equal(foldername_span.textContent, empty_folder.name);
        assert.include(foldericon.className, "ico-folder");
        assert.equal(folderitems_span.textContent, "(empty)");

        // Check that the icon is changed after a click using Simulate function
        Simulate.click(folder_wrapper)
        assert.include(foldericon.className, "ico-folder-open");
    });
});

答案 3 :(得分:0)

只需创建一个Event并发送它:

// Add an event listeners to the document
document.addEventListener('click', function() {
    console.log('test');
});

// Create a new `click` event and `dispatch` it
var event = new MouseEvent('click')
document.dispatchEvent(event)

答案 4 :(得分:0)

Event.initEvent()已过时,现在应改用Event()构造函数。

// Add a click event listener to the document
document.addEventListener('click', function() {
    console.log('test');
});

// Create a click event with optional event initialisers: bubbles, cancelable and composed
var evt = new Event('click', { bubbles: false, cancelable: false, composed: false });

// Event can then be dispatched against any element, not only the document
document.dispatchEvent(evt);
myDiv.dispatchEvent(evt);

除Internet Explorer之外,浏览器支持都很好。

参考文献: