使用react-testing-library进行卸载测试

5
我对查询元素何时/如何更新感到困惑。例如:
我有一个计数按钮。当它计数到3时,它会消失。
import React, { useState } from "react";

export default () => {
  const [count, setCount] = useState(0);

  return (
    <div>
      {count < 3 && (
        <button onClick={() => setCount(count + 1)}>{count}</button>
      )}
    </div>
  );
};

我这样进行测试:

test("Counter counts up and disappears", () => {
  const { queryByText } = render(<App" />);

  const button = queryByText("0");
  expect(button.textContent).toEqual("0");

  fireEvent.click(button);
  expect(button.textContent).toEqual("1");

  fireEvent.click(button);
  expect(button.textContent).toEqual("2");

  fireEvent.click(button);
  expect(button).toBe(null);
});

测试失败,并出现以下错误:
expect(received).toBe(expected)

Expected value to be (using ===):
  null
Received:
  <button>2</button>
1个回答

2
我猜这是关于 react-domjsdom(测试中使用的)的工作原理。

(如果猜测不可接受,请纠正我或让我知道!我会删除这段话。)

  1. queryByText 返回的按钮类型是 HtmlElment

  2. reactreact-dom 只是最小化了 dom 操作的任务,最终还是要使用 jsdom 进行文本更改和按钮删除等操作。

  3. 由于测试工具使用的是 jsdom,我检查了代码中的 removeChild 部分,并认为 它们遵循 W3C 规范。我假设在 dom 操作的层面上,jsdom 会像浏览器一样工作。因此,我模拟了你的代码如下:

const btn = document.getElementById('btn');
const btnContainer = document.getElementById('btnContainer');

btn.textContent = '1';
console.log('btn after click 1: ' + btn);
btn.textContent = '2';
console.log('btn after click 2: ' + btn);
btnContainer.removeChild(btn);
console.log('btn after removed: '+  btn);
<div id='btnContainer'><button id='btn'>0<button></div>

正如你所看到的,在从 div 中移除后,btn 变量仍然是 [object HTMLButtonElement]。也许这类似于对包含一个已定义对象的数组使用 splice,初始对象仍然保持不变?

const obj = { 'a': 1};
const arr = [obj];
arr[0]['a'] = 2;
arr.splice(0, -1);
console.log(obj)


因此,我认为这更多是关于JavaScript垃圾回收的工作原理。另外,在这种情况下可能不要重复使用查询结果,每次查询结果都会更可预期。
附言:我发现有一个方法叫做toBeInTheDocument

为了补充这个答案,绝对地,最好每次执行一个新查询并使用 toBeInTheDocument - Gio Polvara

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接