React测试库:测试元素是否已映射/呈现



问题:

我有一个项目列表,我想通过每个项目name值(字符串(来测试这些项目。我正在使用@testing-library/react,并使测试套件正常工作,但我无法使我的测试正常工作。

概述:

  • 每个item都有一个data-testid="side-menu-link"的测试id。这必须是唯一的吗?还是可以按原样进行测试
  • menuItems由DashboardSettingsUser 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 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>
);
});

您可以有多个testID。否则,就不会有__AllByTestId选择器。这个名字似乎没有经过深思熟虑,因为它与HTML ID相似,必须是唯一的。

如果您使用__ByTestId,但您有多个具有匹配测试id:的元素,则会发生抛出

it("getByTestId will throw with multiple testIDs", () => {
const {getAllByTestId, getByTestId} = render(
<View>
<Text testID="foo">a</Text>
<Text testID="foo">b</Text>
</View>
);
expect(getAllByTestId("foo")).toHaveLength(2); // OK
getByTestId("foo"); // => Error: Found multiple elements with testID: foo
});

要测试映射,可以将测试ID添加到子项并使用上面的模式。

React Native:

import "@testing-library/jest-native/extend-expect";
// ...
it("should find text content in all children", () => {
const {getAllByTestId} = render(
<View>
{[..."abcd"].map((e, i) => 
<View key={e + i} testID="foo"><Text>{e}</Text></View>
)}
</View>
);
expect(getAllByTestId("foo")).toHaveLength(4);

[..."abcd"].forEach((e, i) => {
expect(getAllByTestId("foo")[i]).toHaveTextContent(e);
});
});

反应:

it("should find text content in all children", () => {
const {getAllByTestId} = render(
<ul>
{[..."abcd"].map((e, i) => 
<li key={e + i} data-testid="foo">{e}</li>
)}
</ul>
);
expect(getAllByTestId("foo")).toHaveLength(4);
[..."abcd"].forEach((e, i) => {
expect(getAllByTestId("foo")[i].textContent).toEqual(e);
});
// or:
//const contents = getAllByTestId("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">——您可能正在查找文本内容。


使用的包,供参考:

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",
}
}

每个item都有一个data-testid="side-menu-link"的测试id。这必须是唯一的吗?还是可以按原样进行测试?

测试id必须是唯一的。我看到你在用getByTestId。根据文献记载;getBy*查询返回查询的第一个匹配节点,如果没有元素匹配则抛出错误;如果找到多个匹配则抛出"因此,您的代码会抛出一个错误(假设列表包含多个元素(。

但是,即使RTL没有抛出错误,测试id应该是唯一的也是有道理的。否则,您将如何区分测试中的两个不同元素?

如果出于某种原因,您仍然希望测试id相同,则需要使用不同的查询,例如getAllBy*queryBy*queryAllBy*。有关更多信息,请再次参阅文档。

最新更新