如何使用 Jest 和 React 测试库测试类名

How to test a className with the Jest and React testing library

我完全不熟悉 JavaScript 测试,并且正在使用新的代码库。我想编写一个测试来检查元素上的类名。我正在与 Jest 和 React Testing Library 一起工作。下面我有一个测试,它将根据 variant 属性呈现一个按钮。它还包含一个类名,我想测试一下。

it('Renders with a className equal to the variant', () => {
    const { container } = render(<Button variant="default" />)
    expect(container.firstChild) // Check for className here
})

我尝试 google 获得 属性,就像 Enzyme 对 hasClass 所做的那样,但我找不到任何东西。我如何使用当前的库(React 测试库 和 Jest)解决这个问题?

您可以使用 react-testing-library 轻松做到这一点。

首先,您必须了解containergetByText等的结果仅仅是DOM个节点。您可以像在浏览器中一样与他们互动。

因此,如果您想知道 class 应用于 container.firstChild 的内容,您可以像这样 container.firstChild.className.

如果你在 MDN 中阅读了更多关于 className 的内容,你会看到它 returns all classes应用于由 space 分隔的元素,即:

<div class="foo">     => className === 'foo'
<div class="foo bar"> => className === 'foo bar'

根据您的情况,这可能不是最佳解决方案。不用担心,您可以使用其他浏览器 API,例如 classList.

expect(container.firstChild.classList.contains('foo')).toBe(true)

就是这样!无需学习仅适用于测试的新 API。就像在浏览器中一样。

如果检查 class 是您经常做的事情,您可以通过将 jest-dom 添加到您的项目来简化测试。

然后测试变成:

expect(container.firstChild).toHaveClass('foo')

还有许多其他方便的方法,例如 toHaveStyle 可以帮助您。


附带说明一下,react-testing-library 是一个合适的 JavaScript 测试工具。与其他库相比,它具有许多优点。如果您不熟悉 JavaScript 测试,我鼓励您加入 spectrum forum

您需要了解 react-testing-library 背后的理念,以了解您可以做什么和不能做什么;

react-testing-library 背后的目标是让测试避免包含组件的实现细节,而是专注于编写让您有信心的测试打算。

因此按类名查询元素不符合 react-testing-library 理念,因为它包含实现细节。类名实际上是元素的实现细节,不是最终用户会看到的,并且在元素的生命周期中随时可能发生变化。

因此,不要通过用户看不到的内容和随时可能更改的内容来搜索元素,而只需尝试使用用户可以看到的内容(例如文本、标签或在元素中保持不变的内容)进行搜索元素的生命周期,如 data-id.

因此,为了回答您的问题,不建议测试类名,因此您不能使用 react-testing-library 进行测试。尝试使用其他测试库,例如 Enzymereact-dom test utils.

您可以使用 testing-library/jest-dom 个自定义匹配器。

The @testing-library/jest-dom library provides a set of custom jest matchers that you can use to extend jest. These will make your tests more declarative, clear to read and to maintain.

https://github.com/testing-library/jest-dom#tohaveclass

it('Renders with a className equal to the variant', () => {
    const { container } = render(<Button variant="default" />)

    expect(container.firstChild).toHaveClass('class-you-are-testing') 
})

这可以在 setupTest.js 文件中全局设置

import '@testing-library/jest-dom/extend-expect';
import 'jest-axe/extend-expect';
// etc

库允许访问普通的 DOM 选择器,所以我们也可以简单地这样做:

it('Renders with a className equal to the variant', () => {
    const { container } = render(<Button variant="default" />)
    expect(container.getElementsByClassName('default').length).toBe(1);
});
    // Link.react.test.js
import React from 'react';
import ShallowRenderer from 'react-test-renderer/shallow';
import App from './../../src/App'
describe('React', () => {
  it('className', () => {
    const renderer = new ShallowRenderer();
    renderer.render(<App />);
    const result = renderer.getRenderOutput();
    expect(result.props.className.split(' ').includes('welcome-framework')).toBe(true);
  });
});

您应该使用 Jest 中的 toHaveClass。无需添加更多逻辑。

it('Renders with a className equal to the variant', () => {
    const { container } = render(<Button variant="default" />)
    expect(container.firstChild).toHaveClass(add you className);
//You Can Also You Screen Instead Of Using Container Container Not Recommended To Use As Documentation Said
    expect(screen.getByRole('button')).toHaveClass(add you className)
})