React 测试库:测试元素是否已被映射/渲染

IT技术 reactjs react-native unit-testing testing react-testing-library
2021-05-20 19:14:24

问题:

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

概述:

  • 每个item都有一个测试 id data-testid="side-menu-link"这必须是唯一的还是可以按原样进行测试?
  • 的的菜单项包括像琴弦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>
  );
});
2个回答

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

测试 ID 必须是唯一的。我看到你正在使用getByTestId. 根据文档,“getBy*查询返回查询的第一个匹配节点,如果没有元素匹配或找到多个匹配,抛出错误。” 所以你的代码会抛出一个错误(假设列表包含多个元素)。

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

如果由于某种原因,你还是要测试ID是一样的,你需要使用不同的查询,例如getAllBy*queryBy*queryAllBy*同样,请参阅文档以获取更多信息。

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

如果您使用__ByTestId了多个具有匹配测试 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
});

要测试地图,您可以向子项添加测试 ID 并使用上述模式。

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"]);
});

也可以将 a 添加testID到映射列表元素的父级,选择父级,然后遍历其.children数组以对每个子树进行断言。

请注意testIDRN 和data-testidReact之间的差异


作为旁注,我不确定

expect(getByTestId('side-menu-link')).toHaveAttribute('User Preferences')

在这里很有意义。属性是<div this_is_an_attribute="foo">——您可能正在寻找文本内容。


使用的包,供参考:

react本机

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