109

我对 JavaScript 测试完全陌生,并且正在使用新的代码库。我想编写一个测试来检查元素上的 className。我正在使用 Jest 和React 测试库。下面我有一个测试,它将根据variant道具呈现一个按钮。它还包含一个类名,我想对其进行测试。

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

我试图用谷歌搜索像 Enzyme 一样的属性hasClass,但我找不到任何东西。如何使用当前的库(React 测试库和 Jest)解决这个问题?

4

6 回答 6

159

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

首先,您必须了解,container或者getByTextetc. 的结果仅仅是 DOM 节点。您可以像在浏览器中一样与它们进行交互。

所以,如果你想知道应用了什么类,container.firstChild你可以这样做container.firstChild.className

如果您classNameMDN中了解更多信息,您会看到它返回应用到您的元素的所有类,以空格分隔,即:

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

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

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

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

如果检查一个类是你经常做的事情,你可以通过将jest-dom添加到你的项目中来使测试更容易。

然后测试变为:

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

还有很多其他方便的方法toHaveStyle可以帮助你。


附带说明一下,react-testing-library 是一个合适的 JavaScript 测试工具。与其他库相比,它具有许多优点。如果您是 JavaScript 测试的新手,我鼓励您加入频谱论坛。

于 2018-11-20T10:56:15.903 回答
48

该库提供对普通 DOM 选择器的访问,因此我们也可以简单地这样做:

it('Renders with a className equal to the variant', () => {
    const { container } = render(<Button variant="default" />)
    expect(container.getElementsByClassName('default').length).toBe(1);
});
于 2020-12-03T01:07:57.977 回答
30

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

react-testing-library背后的目标是让测试避免包含组件的实现细节,而是专注于编写测试,让您对它们预期的目标充满信心。

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

因此,不要通过用户看不到的内容以及可以随时更改的内容来搜索元素,而是尝试使用用户可以看到的内容进行搜索,例如文本、标签或在元素生命周期中保持不变的内容像数据ID。

所以要回答你的问题,不建议测试类名,因此你不能用react-testing-library来做。尝试使用其他测试库,例如Enzymereact-dom test utils

于 2019-05-28T05:58:10.110 回答
22

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

@testing-library/jest-dom 库提供了一组自定义的 jest 匹配器,您可以使用它们来扩展 jest。这些将使您的测试更具声明性,更易于阅读和维护。

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
于 2020-06-12T11:01:56.383 回答
2

简单地说,你应该使用 toHaveClass from Jest 无需添加更多逻辑

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)
})
于 2021-10-13T20:21:00.983 回答
-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);
  });
});
于 2021-05-20T07:07:24.730 回答