Reaction测试库:测试元素是否已Map/呈现

0x6upsns  于 2022-10-15  发布在  React
关注(0)|答案(2)|浏览(157)

问题:

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

概述:

  • 每个item的测试ID为data-testid="side-menu-link"。这是否必须是唯一的,或者可以按原样进行测试?
  • 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项:

// 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>
  );
});
fgw7neuy

fgw7neuy1#

您可以有多个testID。否则,不会有__AllByTestId选择器。这个名字似乎没有经过深思熟虑,因为它与HTMLID相似,必须是唯一的。
如果您使用__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
});

要测试Map,您可以将测试ID添加到子Map并使用上面的模式。
原生React:

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

React:

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添加到Map列表元素的父级,选择父级,然后遍历其.children数组以对每个子树进行Assert。
注意RN中的testID和Reaction中的data-testid之间的差异。
顺便说一句,我不确定

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

ws51t4hk2#

每个item具有测试ID data-testid="side-menu-link"。这是否必须是唯一的,或者可以按原样进行测试?
测试ID必须是唯一的。我看到你在用getByTestId。根据文档介绍,getBy*查询返回查询的第一个匹配节点,如果没有元素匹配,则抛出错误,或者如果找到多个匹配,则抛出错误。因此,您的代码将抛出一个错误(假设列表包含多个元素)。
但是,即使RTL没有抛出错误,测试ID应该是唯一的也是有意义的。否则,您将如何区分测试中的两个不同元素?
如果出于某种原因,您仍然希望测试ID相同,则需要使用不同的查询,如getAllBy*queryBy*queryAllBy*。同样,请参阅the documentation以了解更多信息。

相关问题