React测试库检查具有test-dataid的div内的文本

huangapple go评论66阅读模式
英文:

React testing library check the text inside a div with test-dataid

问题

以下是翻译的内容:

我有一个名为“order details”的React组件。在那里,我基于这个数组打印了有关订单的7个详细信息。

const items = [
    {
      name: "Order ID",
      value: "01234567890",
    },
    {
      name: "Channel ID",
      value: "88888",
    },
    {
      name: "Sales Channel",
      value: "Shopify",
    },
    {
      name: "Order Date",
      value: "23-09-2022 | 00:00:00",
    },
    {
      name: "Order Total",
      value: "£10.00 GBP",
    },
    {
      name: "Shipping Method Selected",
      value: "Method",
    },
    {
      name: "Tags",
      value: "Shopify",
    },
];

在我的组件中,我循环遍历这个数组并像这样打印它:

items.map(item => (
  <div data-testid={item.name}>
    <div>{item.name}</div>
    <div>{item.value}</div>
  </div>
))

我想编写一个单元测试,以确保组件成功渲染了这些数据。

我可以轻松地为name属性编写如下测试:

const orderIdDiv = screen.getByText(/order id/i);
const channelIdDiv = screen.getByText(/channel id/i);

expect(orderIdDiv).toBeInTheDocument();
expect(channelIdDiv).toBeInTheDocument();

但是对于value属性,我想确保该值打印在相关的div中(例如,值88888应该打印在Channel ID div旁边,而不是其他位置)。

因此,我编写了以下代码:

// 通过测试ID获取元素
const orderIdDataElement = screen.getByTestId(/order id/i);
// 获取该元素中的文本
const orderIdData = within(orderIdDataElement).getByText(/012345678901222/i);

expect(orderIdDataElement).toBeInTheDocument();
expect(orderIdData).toBeInTheDocument();

请注意,这个测试总是通过,但要注意,getByText中的文本"012345678901222"是错误的。尽管如此,测试仍然通过了。

我的代码有什么问题?

英文:

I have a React component called order details. There I print 7 details about the order based on this array.

 const items = [
    {
      name: &quot;Order ID&quot;,
      value: &quot;01234567890&quot;,
    },
    {
      name: &quot;Channel ID&quot;,
      value: &quot;88888&quot;,
    },
    {
      name: &quot;Sales Channel&quot;,
      value: &quot;Shopify&quot;,
    },
    {
      name: &quot;Order Date&quot;,
      value: &quot;23-09-2022 | 00:00:00&quot;,
    },

    {
      name: &quot;Order Total&quot;,
      value: &quot;&#163;10.00 GBP&quot;,
    },
    {
      name: &quot;Shipping Method Selected&quot;,
      value: &quot;Method&quot;,
    },
    {
      name: &quot;Tags&quot;,
      value: &quot;Shopify&quot;,
    },
  ];

In my component, I loop this array and print it like this

 items.map(item=&gt;&lt;div data-testid={item.name}&gt;
  &lt;div&gt;
  {item.name}
  &lt;/div&gt;
  &lt;div&gt;
  {item.value}
  &lt;/div&gt;
  &lt;/div&gt;)

I do want to write a unit test to this that will make sure the component is rendered successfully with the data.

I can easily write for name properties like this

const orderIdDiv = screen.getByText(/order id/i);
const chanelIdDiv = screen.getByText(/channel id/i)



expect(orderIdDiv).toBeInTheDocument();
expect(chanelIdDiv).toBeInTheDocument();

But for the value properties, I want to make sure that the value is printed in the relevant div (Eg:- value 88888 should be printed next to the Chanel ID div. Not next to something else )

So I wrote this code

// GET THE ELEMENT BY TEST ID
const orderIdDataElement = screen.getByTestId(/order id/i);
// GET THE TEXT IN THAT ELEMENT
const orderIdData = within(orderIdDataElement).getByText(/012345678901222/i);

expect(orderIdLabelElement).toBeInTheDocument();
expect(orderIdData).toBeInTheDocument();

This test always passes please note that the getByText 012345678901222 is wrong. Still, the test got passed.
What is wrong with my code?

答案1

得分: 2

我重现了你的示例,测试失败,就像它们应该一样。通过正则表达式访问元素是可以的,尽管可能不是最佳方法。

当我将orderIdData的测试更改为

const orderIdData = within(orderIdDataElement).getByText(/01234567890/i);
expect(orderIdData).toBeInTheDocument();

测试通过了。

我无法重现这个问题。你可能没有在问题中包含一些缺失的信息。

还请注意,你的测试有这一行

expect(orderIdLabelElement).toBeInTheDocument();

但你没有展示我们orderIdLabelElement在哪里定义。

我首选测试你的React组件的方法是遍历项目,并且对于每个项目,测试divtextContent属性是否如预期那样。以下是一个执行此操作的工作测试文件:

import React from 'react';
import '@testing-library/jest-dom';
import { render, screen } from "@testing-library/react";

const items = [
  {
    name: "Order ID",
    value: "01234567890",
  },
  {
    name: "Channel ID",
    value: "88888",
  },
  {
    name: "Sales Channel",
    value: "Shopify",
  },
  {
    name: "Order Date",
    value: "23-09-2022 | 00:00:00",
  },

  {
    name: "Order Total",
    value: "£10.00 GBP",
  },
  {
    name: "Shipping Method Selected",
    value: "Method",
  },
  {
    name: "Tags",
    value: "Shopify",
  },
];

items.map((item) => {
  it(`renders the correct content for ${item.name}`, () => {
    render(
      // *** 用渲染你的组件的代码替换这里 ***
      <>
        {items.map((item) => (
          <div key={item.name} data-testid={item.name}>
            <div>
              {item.name}
            </div>
            <div>
              {item.value}
            </div>
          </div>
        ))}
      </>
    );

    const renderedItem = screen.getByTestId(item.name);
    expect(renderedItem.textContent).toEqual(`${item.name}${item.value}`)
  });
});

还有一些额外的要点:

  • 我添加了key属性到映射的项目,以消除React的警告。React文档解释了为什么建议这样做。
  • 最佳实践是尽量避免通过测试ID获取元素,但由于你的问题标题明确指定了test-dataid,我不会详细讨论这一点。你可以在Testing Library文档中了解更多信息。

希望这对你有所帮助。愿你编码愉快!

英文:

I reproduced your example and the tests failed, like they should. It is OK to access elements by regular expression like you have done, although it may not be the best way.

When I changed the orderIdData test to

const orderIdData = within(orderIdDataElement).getByText(/01234567890/i);
expect(orderIdData).toBeInTheDocument();

the test passed.

I can't reproduce the problem. There must be some missing information that you haven't included in your question.

Also note that your test has the line

expect(orderIdLabelElement).toBeInTheDocument();

but you haven't shown us where orderIdLabelElement is defined.

My preferred method of testing your React component would be to loop through the items and, for each one, test that the textContent property of the div is as expected. Here is a working test file that does this:

import React from &#39;react&#39;;
import &#39;@testing-library/jest-dom&#39;;
import { render, screen } from &quot;@testing-library/react&quot;;
const items = [
{
name: &quot;Order ID&quot;,
value: &quot;01234567890&quot;,
},
{
name: &quot;Channel ID&quot;,
value: &quot;88888&quot;,
},
{
name: &quot;Sales Channel&quot;,
value: &quot;Shopify&quot;,
},
{
name: &quot;Order Date&quot;,
value: &quot;23-09-2022 | 00:00:00&quot;,
},
{
name: &quot;Order Total&quot;,
value: &quot;&#163;10.00 GBP&quot;,
},
{
name: &quot;Shipping Method Selected&quot;,
value: &quot;Method&quot;,
},
{
name: &quot;Tags&quot;,
value: &quot;Shopify&quot;,
},
];
items.map((item) =&gt; {
it(`renders the correct content for ${item.name}`, () =&gt; {
render(
// *** Replace this with the code that renders your component ***
&lt;&gt;
{items.map((item) =&gt; (
&lt;div key={item.name} data-testid={item.name}&gt;
&lt;div&gt;
{item.name}
&lt;/div&gt;
&lt;div&gt;
{item.value}
&lt;/div&gt;
&lt;/div&gt;
))}
&lt;/&gt;
);
const renderedItem = screen.getByTestId(item.name);
expect(renderedItem.textContent).toEqual(`${item.name}${item.value}`)
});
});

A couple of extra points:

  • I've added a key property to the mapped items to silence a warning from React. The React docs explain why this is recommended.
  • It is best practice not to get elements by Test ID if you can avoid it, but I won't go into this in detail as your question title specifically states test-dataid. You can read more about this in the Testing Library docs.

Hope this helps. Happy coding!

huangapple
  • 本文由 发表于 2023年2月8日 17:53:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/75383997.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定