React 测试库:测试元素是否已被映射/渲染 [英] React Testing Library: Test if Elements have been mapped/rendered
问题描述
问题:
我有一个项目列表,我想通过每个项目 name
值(字符串)来测试.我正在使用 @testing-library/react
并让测试套件正常工作,但我无法让我的测试工作.
概述:
- 每个
item
都有一个data-testid="side-menu-link"
的测试ID.这必须是唯一的还是可以按原样进行测试? - 菜单项由
Dashboard
、Settings
和User Preferences
等字符串组成
DisplayItems.test.tsx:
//导入:依赖从反应"导入反应;从'@testing-library/react'导入{渲染,屏幕};//导入:应用从'../../App'导入应用程序;//侧面菜单:仪表板test('正确渲染仪表板', () => {//渲染:应用const { getByTestId } = render( );//预计expect(getByTestId('side-menu-link')).toHaveAttribute('Dashboard')});//侧边菜单:用户首选项test('正确渲染仪表板', () => {//渲染:应用const { getByTestId } = render( );//预计expect(getByTestId('side-menu-link')).toHaveAttribute('User Preferences')});
地图项目:
//映射菜单项return menuItems.map((menuItem, i) => {返回 (<Link data-testid="side-menu-link";key={i} href=#";className="side-menu-link";to={`/${menuItem.itemName}`}><div className={props.currenttab === `${menuItem.itemName}` ?'side-menu-item-container-selected-light':'side-menu-item-container-light'}>{menuItem.itemIcon}<p className={props.currenttab === `${menuItem.itemName}` ?'side-menu-title-selected-light':'side-menu-title-light'}>{menuItem.itemName}</p>
</链接>);});
您可以有多个 testID
.否则,就不会有 __AllByTestId
选择器.这个名字似乎没有经过深思熟虑,因为它与 HTML id 相似,必须是唯一的.
如果您使用 __ByTestId
但您有多个具有匹配测试 ID 的元素,则会发生抛出:
it(queryByTestId 将抛出多个 testID", () => {const {queryAllByTestId, queryByTestId} = render(<查看><Text testID="foo">a</Text><Text testID="foo">b</Text></查看>);期望(queryAllByTestId(foo")).toHaveLength(2);//好的queryByTestId("foo");//=>错误:找到多个 testID 为 foo 的元素});
要测试地图,您可以向子项添加测试 ID 并使用上述模式.
反应原生:
import "@testing-library/jest-native/extend-expect";//...it(应该在所有孩子中找到文本内容", () => {const {queryAllByTestId} = 渲染(<查看>{[...abcd"].map((e, i) =><查看键={e + i} testID=foo"><Text>{e}</Text></View>)}</查看>);期望(queryAllByTestId(foo")).toHaveLength(4);[...abcd"].forEach((e, i) => {期望(queryAllByTestId(foo")[i]).toHaveTextContent(e);});});
反应:
it(应该在所有孩子中找到文本内容", () => {const {queryAllByTestId} = 渲染(<ul>{[...abcd"].map((e, i) =><li key={e + i} data-testid=foo">{e}</li>)});期望(queryAllByTestId(foo")).toHaveLength(4);[...abcd"].forEach((e, i) => {期望(queryAllByTestId(foo")[i].textContent).toEqual(e);});//或者://const contents = queryAllByTestId("foo").map(e => e.textContent);//expect(contents).toEqual([...abcd"]);});
还可以将 testID
添加到映射列表元素的父级,选择父级,然后遍历其 .children
数组以对每个子级进行断言树.
注意 RN 中的 testID
和 React 中的 data-testid
之间的区别.
顺便说一句,我不确定
expect(getByTestId('side-menu-link')).toHaveAttribute('User Preferences')
在这里很有意义.属性是 <div this_is_an_attribute="foo">
-- 您可能正在寻找文本内容.
使用的包,供参考:
反应原生
{依赖关系":{反应":^ 17.0.2",react-dom":^17.0.2",反应原生":^ 0.64.0",react-native-web":^0.15.6";},开发依赖":{@babel/core":^7.13.15",@testing-library/jest-native":^4.0.1",@testing-library/react-native":^7.2.0",babel-jest":^26.6.3",开玩笑":^26.6.3",metro-react-native-babel-preset":^0.65.2",反应测试渲染器":^ 17.0.2";}}
反应
{依赖关系":{@babel/runtime":7.10.5",反应":16.13.1",反应DOM":16.13.1",},开发依赖":{@babel/core":7.10.5",@babel/plugin-proposal-class-properties":7.10.4",@babel/preset-env":7.10.4",@babel/preset-react":7.10.4",@testing-library/dom":7.21.0",@testing-library/jest-dom":^5.11.1",@testing-library/react":10.4.7",@testing-library/react-hooks":3.3.0",@testing-library/user-event":12.0.11",babel-jest":26.1.0",开玩笑":26.1.0",jest-environment-jsdom":26.1.0",反应测试渲染器":16.13.1",}}
Issue:
I have a list of Items that I want to test by each one of the items name
value (string). I'm using @testing-library/react
and have the test suite correctly working, but I can't get my test to work.
Overview:
- Each
item
has a test id ofdata-testid="side-menu-link"
. Does this have to be unique or can it be tested as is? - The menuItems consist of strings like
Dashboard
,Settings
, andUser Preferences
DisplayItems.test.tsx:
// Imports: Dependencies
import React from 'react';
import { render, screen } from '@testing-library/react';
// Imports: App
import App from '../../App';
// Side Menu: Dashboard
test('Renders Dashboard correctly', () => {
// Render: App
const { getByTestId } = render(<App />);
// Expect
expect(getByTestId('side-menu-link')).toHaveAttribute('Dashboard')
});
// Side Menu: User Preferences
test('Renders Dashboard correctly', () => {
// Render: App
const { getByTestId } = render(<App />);
// Expect
expect(getByTestId('side-menu-link')).toHaveAttribute('User Preferences')
});
Map Items:
// Map Menu Items
return menuItems.map((menuItem, i) => {
return (
<Link data-testid="side-menu-link" key={i} href="#" className="side-menu-link" to={`/${menuItem.itemName}`}>
<div className={props.currenttab === `${menuItem.itemName}` ? 'side-menu-item-container-selected-light' : 'side-menu-item-container-light'}>
{menuItem.itemIcon}
<p className={props.currenttab === `${menuItem.itemName}` ? 'side-menu-title-selected-light' : 'side-menu-title-light'}>{menuItem.itemName}</p>
</div>
</Link>
);
});
You can have multiple testID
s. Otherwise, there wouldn't be __AllByTestId
selectors. The name wasn't well-thought out, it seems, because of similarity to HTML ids which must be unique.
A throw happens if you use __ByTestId
yet you have multiple elements with the matching test id:
it("queryByTestId will throw with multiple testIDs", () => {
const {queryAllByTestId, queryByTestId} = render(
<View>
<Text testID="foo">a</Text>
<Text testID="foo">b</Text>
</View>
);
expect(queryAllByTestId("foo")).toHaveLength(2); // OK
queryByTestId("foo"); // => Error: Found multiple elements with testID: foo
});
To test a map, you can add test ids to the children and use the above pattern.
React Native:
import "@testing-library/jest-native/extend-expect";
// ...
it("should find text content in all children", () => {
const {queryAllByTestId} = render(
<View>
{[..."abcd"].map((e, i) =>
<View key={e + i} testID="foo"><Text>{e}</Text></View>
)}
</View>
);
expect(queryAllByTestId("foo")).toHaveLength(4);
[..."abcd"].forEach((e, i) => {
expect(queryAllByTestId("foo")[i]).toHaveTextContent(e);
});
});
React:
it("should find text content in all children", () => {
const {queryAllByTestId} = render(
<ul>
{[..."abcd"].map((e, i) =>
<li key={e + i} data-testid="foo">{e}</li>
)}
</ul>
);
expect(queryAllByTestId("foo")).toHaveLength(4);
[..."abcd"].forEach((e, i) => {
expect(queryAllByTestId("foo")[i].textContent).toEqual(e);
});
// or:
//const contents = queryAllByTestId("foo").map(e => e.textContent);
//expect(contents).toEqual([..."abcd"]);
});
It's also possible to add a testID
to the parent of the mapped list elements, select the parent, then traverse over its .children
array to make assertions on each child tree.
Note the differences between testID
in RN and data-testid
in React.
As a side note, I'm not sure
expect(getByTestId('side-menu-link')).toHaveAttribute('User Preferences')
makes much sense here. attributes are <div this_is_an_attribute="foo">
-- you're probably looking for text content.
Packages used, for reference:
React Native
{
"dependencies": {
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-native": "^0.64.0",
"react-native-web": "^0.15.6"
},
"devDependencies": {
"@babel/core": "^7.13.15",
"@testing-library/jest-native": "^4.0.1",
"@testing-library/react-native": "^7.2.0",
"babel-jest": "^26.6.3",
"jest": "^26.6.3",
"metro-react-native-babel-preset": "^0.65.2",
"react-test-renderer": "^17.0.2"
}
}
React
{
"dependencies": {
"@babel/runtime": "7.10.5",
"react": "16.13.1",
"react-dom": "16.13.1",
},
"devDependencies": {
"@babel/core": "7.10.5",
"@babel/plugin-proposal-class-properties": "7.10.4",
"@babel/preset-env": "7.10.4",
"@babel/preset-react": "7.10.4",
"@testing-library/dom": "7.21.0",
"@testing-library/jest-dom": "^5.11.1",
"@testing-library/react": "10.4.7",
"@testing-library/react-hooks": "3.3.0",
"@testing-library/user-event": "12.0.11",
"babel-jest": "26.1.0",
"jest": "26.1.0",
"jest-environment-jsdom": "26.1.0",
"react-test-renderer": "16.13.1",
}
}
这篇关于React 测试库:测试元素是否已被映射/渲染的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!