检查按钮在React-Testing-Library中是否被禁用

Nik*_*hin 5 reactjs react-testing-library

我有一个React组件,它会生成一个按钮,其中的内容包含<span>类似这样的元素:

function Click(props) {
    return (
        <button disable={props.disable}>
            <span>Click me</span>
        </button>
    );
}
Run Code Online (Sandbox Code Playgroud)

我想使用react-testing-librarymocha+ 测试该组件的逻辑chai

我目前遇到的问题是getByText("Click me")选择器返回<span>DOM节点,但是对于测试,我需要检查disable<button>节点的属性。处理此类测试用例的最佳实践是什么?我看到了一些解决方案,但是所有这些听起来都有些偏离:

  1. 使用data-test-id<button>元素
  2. 选择<Click />组件的祖先之一,然后选择within(...)此范围的按钮
  3. 单击带有的选定元素,fireEvent并检查没有任何反应

您可以提出更好的方法吗?

Chr*_*ris 14

我会礼貌地争辩说你正在测试一个实现细节,这是反应测试库不鼓励的。

您的测试越接近软件的使用方式,它们就越能给您带来信心。

如果按钮被禁用,用户不会看到禁用的道具,而是看不到任何反应。如果启用按钮,用户不会看到禁用道具的遗漏,而是会看到发生了一些事情。

我相信你应该对此进行测试:

const Button = (props) => (
  <button 
    type="submit" 
    onClick={props.onClick} 
    disabled={props.disabled}
  >
    Click me
  </button>
);

describe('Button', () => {
  it('will call onClick when enabled', () => {
    const onClick = jest.fn();
    render(<Button onClick={onClick} disabled={false} />);
    userEvent.click(getByRole('button', /click me/i));
    expect(onClick).toHaveBeenCalledTimes(1);
  });

  it('will not call onClick when disabled', () => {
    const onClick = jest.fn();
    render(<Button onClick={onClick} disabled={true} />);
    userEvent.click(getByRole('button', /click me/i));
    expect(onClick).not.toHaveBeenCalled();
  });
})
Run Code Online (Sandbox Code Playgroud)

  • 好点子!不过我认为,在禁用按钮的情况下,您可以牺牲概念的纯粹性并测试“实现细节”,特别是当您测试“disabled”属性时,该属性是具有固定行为的 HTML 规范的一部分。您能否提供一些示例来展示测试“disabled”属性的缺点和模拟“click”回调的优点,只是为了我的兴趣? (3认同)

Ton*_*yen 11

对于寻找测试的人来说,按钮没有被禁用

import { render } from '@testing-library/react';

const { getByText } = render(Click);
expect(getByText(/Click me/i).getAttribute("disabled")).toBe(null)
Run Code Online (Sandbox Code Playgroud)

  • 使用“.toBeNull()”代替“.toBe(null)”。 (3认同)

joh*_*ter 8

您可以使用toHaveAttributeclosest测试它。

import { render } from '@testing-library/react';

const { getByText } = render(Click);
expect(getByText(/Click me/i).closest('button')).toHaveAttribute('disabled');
Run Code Online (Sandbox Code Playgroud)

  • 请注意,“toHaveAttribute”需要安装 https://github.com/testing-library/jest-dom。 (6认同)
  • 对于使用与 jest 不同的框架的每个人,例如 Jasmine,这样的东西应该可以完成工作: `expect(getByText(/Click me/i).closest('button').hasAttribute('disabled')).toBeTrue() ;` (3认同)
  • 请注意:必须有一个相关的“jsdom”库的最新版本才能在您的示例中使用“closest(...)”函数(v 11.12.0 或更高版本) (2认同)

Mey*_*ehr 7

您可以使用toBeDisabledfrom esting-library/jest-dom,它是一个自定义的笑话匹配器,用于测试DOM的状态:

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


Ult*_*ire 6

toHaveAttribute是使用属性的好选择。

<button data-testid="ok-button" type="submit" disabled>ok</button>

const button = getByTestId('ok-button')
//const button = getByRole('button');

expect(button).toHaveAttribute('disabled')
expect(button).toHaveAttribute('type', 'submit')
expect(button).not.toHaveAttribute('type', 'button')

expect(button).toHaveAttribute('type', expect.stringContaining('sub'))
expect(button).toHaveAttribute('type', expect.not.stringContaining('but'))
Run Code Online (Sandbox Code Playgroud)

希望这会有所帮助。