简体   繁体   English

如何使用 jest 和 react-testing-library 测试元素是否存在?

[英]How do you test for the non-existence of an element using jest and react-testing-library?

I have a component library that I'm writing unit tests for using Jest and react-testing-library.我有一个组件库,我正在为使用 Jest 和 react-testing-library 编写单元测试。 Based on certain props or events I want to verify that certain elements aren't being rendered.基于某些道具或事件,我想验证某些元素没有被渲染。

getByText , getByTestId , etc throw and error in react-testing-library if the element isn't found causing the test to fail before the expect function fires.如果在expect触发之前未找到导致测试失败的元素,则getByTextgetByTestId等会在react-testing-library中抛出错误。

How do you test for something not existing in jest using react-testing-library?你如何使用 react-testing-library 测试 jest 中不存在的东西?

From DOM Testing-library Docs - Appearance and Disappearance来自DOM Testing-library Docs - Appearance and Disappearance

Asserting elements are not present断言元素不存在

The standard getBy methods throw an error when they can't find an element, so if you want to make an assertion that an element is not present in the DOM, you can use queryBy APIs instead:标准getBy方法在找不到元素时会抛出错误,因此如果您想断言某个元素存在于 DOM 中,则可以改用queryBy API:

 const submitButton = screen.queryByText('submit') expect(submitButton).toBeNull() // it doesn't exist

The queryAll APIs version return an array of matching nodes. queryAll APIs 版本返回匹配节点的数组。 The length of the array can be useful for assertions after elements are added or removed from the DOM.数组的长度对于在 DOM 中添加或删除元素后的断言很有用。

 const submitButtons = screen.queryAllByText('submit') expect(submitButtons).toHaveLength(2) // expect 2 elements

not.toBeInTheDocument

The jest-dom utility library provides the .toBeInTheDocument() matcher, which can be used to assert that an element is in the body of the document, or not. jest-dom实用程序库提供了.toBeInTheDocument()匹配器,可用于断言某个元素是否在文档正文中。 This can be more meaningful than asserting a query result is null .这比断言查询结果为null更有意义。

 import '@testing-library/jest-dom/extend-expect' // use `queryBy` to avoid throwing an error with `getBy` const submitButton = screen.queryByText('submit') expect(submitButton).not.toBeInTheDocument()

Use queryBy / queryAllBy .使用queryBy / queryAllBy

As you say, getBy* and getAllBy* throw an error if nothing is found.如您所说,如果未找到任何内容, getBy*getAllBy*抛出错误。

However, the equivalent methods queryBy* and queryAllBy* instead return null or [] :但是,等效方法queryBy*queryAllBy*反而返回null[]

queryBy查询方式

queryBy* queries return the first matching node for a query, and return null if no elements match. queryBy*查询返回查询的第一个匹配节点,如果没有元素匹配,则返回null This is useful for asserting an element that is not present.这对于断言不存在的元素很有用。 This throws if more than one match is found (use queryAllBy instead).如果找到多个匹配项(使用 queryAllBy 代替),则会抛出此问题。

queryAllBy queryAllBy* queries return an array of all matching nodes for a query, and return an empty array ( [] ) if no elements match. queryAllBy queryAllBy*查询返回查询的所有匹配节点的数组,如果没有元素匹配,则返回空数组 ( [] )。

https://testing-library.com/docs/dom-testing-library/api-queries#queryby https://testing-library.com/docs/dom-testing-library/api-queries#queryby

So for the specific two you mentioned, you'd instead use queryByText and queryByTestId , but these work for all queries, not just those two.因此,对于您提到的特定两个,您应该使用queryByTextqueryByTestId ,但这些适用于所有查询,而不仅仅是这两个。

You have to use queryByTestId instead of getByTestId.您必须使用 queryByTestId 而不是 getByTestId。

Here a code example where i want to test if the component with "car" id isn't existing.这是一个代码示例,我想在其中测试具有“car” id 的组件是否不存在。

 describe('And there is no car', () => {
  it('Should not display car mark', () => {
    const props = {
      ...defaultProps,
      base: null,
    }
    const { queryByTestId } = render(
      <IntlProvider locale="fr" messages={fr}>
        <CarContainer{...props} />
      </IntlProvider>,
    );
    expect(queryByTestId(/car/)).toBeNull();
  });
});

getBy* 在找不到元素时抛出错误,因此您可以检查它

expect(() => getByText('your text')).toThrow('Unable to find an element');

Hope this will be helpfull希望这会有所帮助

this table shows why/when function errors此表显示了 function 错误的原因/时间

which functions are asynchronous哪些函数是异步的

what is return statement for function function 的退货单是什么

在此处输入图像描述

You can use react-native-testing-library "getAllByType" and then check to see if the component is null.您可以使用 react-native-testing-library "getAllByType" 然后检查组件是否为空。 Has the advantage of not having to set TestID, also should work with third party components优点是不用设置TestID,也应该和第三方组件一起工作

 it('should contain Customer component', () => {
    const component = render(<Details/>);
    const customerComponent = component.getAllByType(Customer);
    expect(customerComponent).not.toBeNull();
  });

Another solution: you could also use a try/catch block另一种解决方案:您也可以使用try/catch

expect.assertions(1)
try {
    // if the element is found, the following expect will fail the test
    expect(getByTestId('your-test-id')).not.toBeVisible();
} catch (error) {
    // otherwise, the expect will throw, and the following expect will pass the test
    expect(true).toBeTruthy();
}

I recently wrote a method to check visibility of element for a jest cucumber project.我最近写了一个方法来检查 cucumber 项目的元素可见性。

Hope it is useful.希望它有用。

public async checknotVisibility(page:Page,location:string) :Promise<void> 
{
    const element = await page.waitForSelector(location);
    expect(element).not.toBe(location); 
}
// check if modal can be open
const openModalBtn = await screen.findByTestId("open-modal-btn");
fireEvent.click(openModalBtn);

expect(
  await screen.findByTestId(`title-modal`)
).toBeInTheDocument();


// check if modal can be close
const closeModalBtn = await screen.findByTestId(
  "close-modal-btn"
);
fireEvent.click(closeModalBtn);

const sleep = (ms: number) => {
  return new Promise((resolve) => setTimeout(resolve, ms));
};

await sleep(500);
expect(screen.queryByTestId("title-modal")).toBeNull();
const submitButton = screen.queryByText('submit')
expect(submitButton).toBeNull() // it doesn't exist

expect(submitButton).not.toBeNull() // it exist

为我工作(如果你想使用 getByTestId):

expect(() => getByTestId('time-label')).toThrow()

don't want to bury the lead, so here's the right solution ✅不想埋头,所以这是正确的解决方案✅

waitFor(() => queryByTestId(/car/) === null)

There are issues with all of the answers here so far...到目前为止,这里的所有答案都存在问题......

don't use getByTestId , that'll have to wait for the timeout because it's expecting the element to eventually be there.不要使用getByTestId ,那将不得不等待超时,因为它期望元素最终会在那里。 Then it'll throw and you'll have to catch that, which is a less readable test.然后它会抛出,你必须抓住它,这是一个可读性较差的测试。 Finally you could have a RACE CONDITION where getByTestId is evaluated before the element disappears and our test will flake.最后,您可能会遇到一个 RACE CONDITION,其中在元素消失之前评估 getByTestId 并且我们的测试将失败。

Just using queryByTestId without waitFor is a problem if the page is changing at all and the element has not disappeared yet.如果页面发生变化并且元素尚未消失,则仅使用不带queryByTestIdwaitFor是一个问题。 RACE CONDITION比赛条件

deleteCarButton.click();
expect(queryByTestId(/car/)).toBeNull(); //

if expect() gets evaluated before the click handler and render completes we'll have a bad time.如果在单击处理程序和渲染完成之前对 expect() 进行求值,我们就会遇到麻烦。

The default behavior of queryByRole is to find exactly one element. queryByRole的默认行为是只查找一个元素。 If not, it throws an error.如果不是,它会抛出一个错误。 So if you catch an error, this means the current query finds 0 element所以如果你发现一个错误,这意味着当前查询找到 0 个元素

expect(
   ()=>screen.getByRole('button')
).toThrow()

getByRole returns 'null', if it does not find anthing getByRole返回 'null',如果它没有找到 anthing

 expect(screen.queryByRole('button')).toEqual((null))

findByRole runs asynchronously, so it returns a Promise . findByRole异步运行,因此它返回Promise If it does not find an element, it rejects the promise. If you are using this, you need to run async callback如果它没有找到元素,它会拒绝 promise。如果你正在使用它,你需要运行async回调

test("testing", async () => {
  let nonExist = false;
  try {
    await screen.findByRole("button");
  } catch (error) {
    nonExist = true;
  }
  expect(nonExist).toEqual(true);
});
    

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何使用 react-testing-library 和 jest 测试链接 - How to test link using react-testing-library and jest 如何使用 Jest 和 react-testing-library 测试 react-dropzone? - How to test react-dropzone with Jest and react-testing-library? 如何用 jest 和 react-testing-library 测试 react-toastify - How to test react-toastify with jest and react-testing-library 带有 jest 和 react-testing-library 的测试方法 - test method with jest and react-testing-library 如何使用 Jest 和 React-Testing-Library 模拟和测试 scrollBy? - How to mock and test scrollBy with Jest and React-Testing-Library? 如何使用 Jest 和 react-testing-library 测试 useRef? - How to test useRef with Jest and react-testing-library? 如何使用 Jest 和 react-testing-library 测试 Websocket 客户端 - How to test Websocket Client with Jest and react-testing-library 如何使用 React、Jest 和 React-testing-library 为带有令牌的 api 调用编写单元测试? - How can I write unit test for api call with token using React, Jest and React-testing-library? 如何使用 jest、react-testing-library 在 React 中模拟元素上的点击事件 - How to mock a click event on an element in React using jest , react-testing-library 如何使用jest和react-testing-library测试上下文提供的功能? - How can I test functions that are provided by context using jest and react-testing-library?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM