React TDD - 如何获取内部文本?

React TDD - How do I get inner text?

我正在 React 中进行 TDD(使用 Typescript,以防万一)以构建一个非常简单的 oauth 登录页面。因为我希望能够支持多个提供者,所以我对元素进行参数化的第一个测试如下所示:

  it("should have providers", () => {
    const { getAllByRole } = render(<Login></Login>);
    const providers: string[] = getAllByRole("provider").map((element) => {
      return element.innerText;
    });
    expect(providers).toContain("GitHub");
  });

目前我的组件非常简单,现在只有硬编码的元素:

const Login = () => {
  return (
    <div role="login">
      <header>Login with SSO</header>
      <ul>
        <li role="provider">GitHub</li>
      </ul>
    </div>
  );
};

export default Login;

我认为我的测试会将所有元素转换为它们的文本内容(例如:string[]),但我得到的是 undefined

的数组
  ● Login Component › should have providers

    expect(received).toContain(expected) // indexOf

    Expected value: "GitHub"
    Received array: [undefined]

我认为问题是 innerText 没有初始化,我应该调用另一个字段或方法,但 interface HTMLElement 的直接文档或 VSCode 中的智能感知都不是正在向我展示任何明显可以使用的东西。也许我测试集合中的项目的方法可以完全不同?

来自 byrole/#api 文档,

Please note that setting a role and/or aria-* attribute that matches the implicit ARIA semantics is unnecessary and is not recommended as these properties are already set by the browser, and we must not use the role and aria-* attributes in a manner that conflicts with the semantics described. For example, a button element can't have the role attribute of heading, because the button element has default characteristics that conflict with the heading role.

您无法为 li 设置 provider 角色,li 的默认和所需角色是由浏览器设置的 listitem

此外,jestjs使用jsdom作为其测试环境,HTMLELement.innerText 属性在jsdom中没有实现,请参见issue#1245. You can use Node.textContent

Login.tsx:

import React from 'react';

const Login = () => {
  return (
    <div role="login">
      <header>Login with SSO</header>
      <ul>
        <li>GitHub</li>
        <li>Google</li>
      </ul>
    </div>
  );
};

export default Login;

Login.test.tsx:

import { render, screen } from '@testing-library/react';
import React from 'react';
import Login from './Login';

describe('Login', () => {
  it('should have providers', () => {
    const { getAllByRole } = render(<Login />);
    const providers: Array<string | null> = getAllByRole('listitem').map((element) => {
      return element.textContent;
    });
    console.log(providers);
    expect(providers).toContain('GitHub');
  });
});

测试结果:

 PASS  examples/69970652/Login.test.tsx (10.053 s)
  Login
    ✓ should have providers (124 ms)

  console.log
    [ 'GitHub', 'Google' ]

      at Object.<anonymous> (examples/69970652/Login.test.tsx:11:13)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        10.6 s, estimated 11 s