You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vanilla JS应用中Testing Library fireEvent.click()测试无效问题

问题:Jest+Testing Library点击事件测试不通过,DOM数值未递增

手动点击按钮时,.output元素的数值正常递增,但使用fireEvent.click()触发点击后,DOM中的数值未更新,导致测试失败。

相关代码

main.js

const incrementBtn = document.querySelector(".increment");
const outputElement = document.querySelector(".output");
let counter = Number(outputElement.textContent);

function increment() {
  outputElement.textContent = counter++;
}

incrementBtn.addEventListener("click", increment);

main.test.js

import { fireEvent } from "@testing-library/dom";
...
describe("index.html", () => {
  beforeEach(() => {
    dom = new JSDOM(html, { runScripts: "dangerously" });
    container = dom.window.document.body;
  });
  // 测试通过
  it("renders a heading element", () => {
    expect(container.querySelector("h3")).not.toBeNull();
  });
  // 测试不通过
  it("increment a value via JavaScript when the button is clicked", async () => {
    const button = container.querySelector(".increment");
    fireEvent.click(button);  // 触发事件

    expect(container.querySelector(".output")).toHaveTextContent("1"); // 测试失败
  });
});

index.html

<!DOCTYPE html>
<html lang="en">
  <body>
    <div class="wrapper">
      <h3>Counter App</h3>
      <p>The Count is:</p>
      <p class="output">0</p>
      <div class="buttons">
        <button class="increment">
          <svg class="icon icon-plus"><use xlink:href="#icon-plus"></use></svg>
        </button>
        
      </div>
    </div>
    <svg>
      <defs>
        <symbol id="icon-plus" viewBox="0 0 32 32">
          <path
            d="M31 12h-11v-11c0-0.552-0.448-1-1-1h-6c-0.552 0-1 0.448-1 1v11h-11c-0.552 0-1 0.448-1 1v6c0 0.552 0.448 1 1 1h11v11c0 0.552 0.448 1 1 1h6c0.552 0 1-0.448 1-1v-11h11c0.552 0 1-0.448 1-1v-6c0-0.552-0.448-1-1-1z"
          ></path>
        </symbol>
      </defs>
    </svg>
    <script src="main.js"></script>
  </body>
</html>

测试报错信息

● index.html › increment a value via JavaScript when the button is clicked

    expect(element).toHaveTextContent()

    Expected element to have text content:
      1
    Received:
      0

      22 |     fireEvent.click(button);
      23 |
    > 24 |     expect(container.querySelector(".output")).toHaveTextContent("1");
         |                                                ^
      25 |   });
      26 | });
      27 |

      at toHaveTextContent (main.test.js:24:48)
      at tryCatch (main.test.js:2:1)
      at Generator.<anonymous> (main.test.js:2:1)
      at Generator.next (main.test.js:2:1)
      at asyncGeneratorStep (main.test.js:2:1)
      at _next (main.test.js:2:1)
      at main.test.js:2:1
      at Object.<anonymous> (main.test.js:2:1)

Test Suites: 1 failed, 1 total
Tests:       1 failed, 1 passed, 2 total
Snapshots:   0 total
Time:        4.199 s

问题原因及解决方法

原因

问题出在counter++的执行顺序:counter++是后自增运算符,会先返回counter当前的值,再将counter加1。第一次点击时,outputElement.textContent被设置为初始值0,之后counter才变成1,导致DOM显示的数值不符合测试预期。

手动点击时看似正常,是因为用户不会即时校验DOM的瞬间变化,第二次点击时数值会更新为1,但测试是检查第一次点击后的结果,因此暴露了这个逻辑问题。

解决方法

将counter++改为前自增运算符++counter,先完成counter的递增,再将更新后的值赋值给DOM元素:

function increment() {
  outputElement.textContent = ++counter;
}

或者先更新counter再赋值,逻辑更直观:

function increment() {
  counter += 1;
  outputElement.textContent = counter;
}

修改后,第一次点击按钮后.output元素的内容会直接变为1,测试即可通过。

内容的提问来源于stack exchange,提问作者Stanley Ulili

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 07:45:37