首页 > 解决方案 > 使用 jest 模拟 jquery 点击事件

问题描述

我正在尝试为以下 javascript 函数编写单元测试。

const $ = require("jquery");
const Toggle = (function (toggle, $) {
  toggle.clickHandler = () => {
    $(".active").not(this).removeClass("active").next().hide(300);

    $(this).toggleClass("active");

    if (false == $(this).next().is(":visible")) {
      $("#accordion > ul").slideUp(300);
    }
    $(this).next().slideToggle(300);
  };

  $("#accordion > li > div").on("click", toggle.clickHandler);
 
  return {
    toggle,
  };
})({}, $);

module.exports = Toggle.toggle;

我写了以下笑话测试

const toggle = require("./toggle");
const $ = require("jquery");
jest.dontMock("jquery");
jest.dontMock("./acc");

describe("Toggle", () => {
  it("It should call click handler", () => {
    document.body.innerHTML = ` <ul id="accordion">
    <li>
      <div>Sports</div>
      <ul>
        <li><a href="#">Golf</a></li>
        <li><a href="#">Cricket</a></li>
        <li><a href="#">Football</a></li>
      </ul>
    </li>
    </ul>
    `;
    const spy = jest.spyOn(toggle, "clickHandler");
    $("div").trigger("click");
    $("div").trigger("click");

    expect(spy).toBeCalledTimes(2);
  });
});

但是当我运行测试时,我收到以下错误。

预期来电数:2 已接来电数:0

标签: javascriptnode.jsjestjs

解决方案


当您从测试文件开头的 js 文件导入时,到那时您将拥有所有可调用的代码。

这意味着,即使在您的测试被初始化、 $("#accordion > li > div").on("click", toggle.clickHandler);执行之前,正如 DOM 中所指出的那样,点击处理程序也没有注册。

正确的方法是公开一种方法来附加点击处理程序并从您的测试/代码中调用它。就像是:

切换.js

const $ = require("jquery");
const Toggle = (function (toggle, $) {
  toggle.clickHandler = () => {
    $(".active").not(this).removeClass("active").next().hide(300);

    $(this).toggleClass("active");

    if (false == $(this).next().is(":visible")) {
      $("#accordion > ul").slideUp(300);
    }
    $(this).next().slideToggle(300);
    console.log("clicked!");
  };

  toggle.attach = () => { // exposing method to attach handlers
    $("#accordion > li > div").on("click", toggle.clickHandler);
  };

  return {
    toggle
  };
})({}, $);

module.exports = Toggle.toggle;

切换.test.js

describe("Toggle", () => {
  it("It should call click handler", async () => {
    document.body.innerHTML = ` <ul id="accordion">
    <li>
      <div>Sports</div>
      <ul>
        <li><a href="#">Golf</a></li>
        <li><a href="#">Cricket</a></li>
        <li><a href="#">Football</a></li>
      </ul>
    </li>
    </ul>
    `;
    const spy = jest.spyOn(toggle, "clickHandler");
    toggle.attach(); // attach handlers
    $("div").trigger("click");
    $("div").trigger("click");

    return new Promise((res, rej) => {
      expect(spy).toBeCalledTimes(2);
      res();
    });
  });
});

推荐阅读