如何使用React-Testing-Library选中Material-UI Checkbox?

时间:2018-11-12 23:36:15

标签: material-ui react-testing-library

似乎就像Material UI的工作方式是单击复选框时它呈现一个不同的SVG,并且不更改属性或实际输入元素上的任何内容。那么,我该如何实际测试元素是否按照react-testing-library的原则进行检查?

这是

的粗略示例
// Checkbox component usage
export const CheckBoxContainer = () => 
<Checkbox
  inputProps={{ 'data-testid': `clickable-checkbox-1234` }}
  data-testid={`checkbox-1234`}
/>

// test
test('check the box', async () => {
  const { getByTestId } = render(<CheckBoxContainer />);
  await waitForElement(() => getByTestId(`checkbox-1234`));
  const checkbox = getByTestId(`checkbox-1234`);
  fireEvent.click(getByTestId(`clickable-checkbox-1234`));
  expect(checkbox).toHaveAttribute('checked');
});

// Generated HTML by Material UI
<span class="MuiButtonBase-root-54 MuiIconButton-root-48 MuiSwitchBase-root-231 MuiCheckbox-root-225 MuiCheckbox-colorSecondary-230 MuiSwitchBase-checked-232 MuiCheckbox-checked-226" data-testid="checkbox-1234">
  <span class="MuiIconButton-label-53">
    <svg class="MuiSvgIcon-root-57" focusable="false" viewBox="0 0 24 24" aria-hidden="true" role="presentation">
      <path d="M19 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.11 0 2-.9 2-2V5c0-1.1-.89-2-2-2zm-9 14l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"></path>
    </svg>
    <input class="MuiSwitchBase-input-234" type="checkbox" data-indeterminate="false" data-testid="clickable-checkbox-1234" value="">
  </span>
  <span class="MuiTouchRipple-root-66">
  </span>
</span>

7 个答案:

答案 0 :(得分:3)

Since the checkbox is rendering an input I would work with it rather than focusing on the image.

You could do something like this:

const checkbox = getByTestId('checkbox-1234').querySelector('input[type="checkbox"]')
expect(checkbox).toHaveProperty('checked', true)

答案 1 :(得分:2)

我发现最容易找到复选框的方法是在其上添加标签

<FormControlLabel
  htmlFor="first-checkBox"
  label="First Checkbox"
  control={ <Checkbox
        checked={checked}
        onChange={handleChange}
        inputProps={{ 'aria-label': 'primary checkbox' }}
      />
  }
/>

稍后在测试案例中

const checkboxEl = screen.getByLabelText('First Checkbox') as HTMLInputElement
expect(checkboxEl).toBeChecked()

如果由于未将toBeChecked识别为可用断言的一部分而导致测试失败,是因为您需要导入

导入'@ testing-library / jest-dom / extend-expect'

答案 2 :(得分:0)

弄清楚了。需要在DOM上使用pip3 install azure getter,而不要尝试检查checked属性。发现了解释此问题的问题:https://github.com/facebook/react/issues/7051#issuecomment-334018747

,此Codepen演示了React中checked属性如何不变: https://codepen.io/gaearon/pen/wgedvV?editors=0010

赞: checked

答案 3 :(得分:0)

在OnChange函数中,您可以访问事件对象已选中值。

OnChange(event:object, checked:boolean)

这写在文档中。

另一种方法是从事件中访问选中属性,如下所示:

event.target.checked

这也在文档中指定。

文档:https://material-ui.com/api/checkbox/

答案 4 :(得分:0)

似乎在JSDOM中,checked属性没有得到更新,例如

      fireEvent.click(input)
      console.log(input.checked) //false
      fireEvent.click(input)
      console.log(input.checked) //false

很难确定复选框的当前状态。由于fireEvent.click(input)本质上是一个切换,因此如果您有一个测试需要将该值设置为true(勾选),则无论复选框的初始状态如何,它都会变得棘手。您可能有一个更新表格,其中可以基于许多不同的服务器数据固定装置来选中/不选中复选框的初始状态。幸运的是,使用MUI,我们可以通过检测周围的DOM类来确定状态。所以我做了以下辅助函数...

const setMuiCheckBox = (input: HTMLInputElement, newValue: boolean) => {
  // find the root span of our checkbox
  const root = input.closest('.MuiButtonBase-root')
  if (root) {
    const isChecked = root.classList.contains('Mui-checked')
    if (isChecked !== newValue) {
      fireEvent.click(input)
    }
  }
}

答案 5 :(得分:0)

试试这个,

import React from 'react';
import {useState, useEffect} from 'react';

import FormControlLabel from '@material-ui/core/FormControlLabel';
import Checkbox from '@material-ui/core/Checkbox';

const CheckBox = () => {
    const [rememberMe, setRememberMe] = useState(false);
    
    const handleRememberMeChange = () => {
        if (rememberMe === true || rememberMe === false){
            setRememberMe(!rememberMe);
        }
        else{
            setRememberMe(true);
        }
    };

    return (
        <FormControlLabel
            control={<Checkbox value="remember" color="primary" />}
            label="Remember me"
            onChange = {handleRememberMeChange}
        />
    );
}

export default CheckBox;

Checkbox 的值作为布尔值存储在状态中。

更新: 显然,您可以在处理程序中使用 event.target.checked 获取 Checkbox 的值。所以上面的处理程序可以是,

    const handleRememberMeChange = (event) => {
        setRememberMe(event.target.checked);
    };

答案 6 :(得分:0)

我的复选框组件受到控制,单击处理程序会更改父组件的状态,然后将其传递给复选框。因此,我使用 mockImplementation 重新渲染具有所需 checked

的组件
test('calls handleSelect with correct argument on click', () => {
    const mockSelectOne = jest.fn();
    const { getByRole, rerender } = render(<Checkbox onClick={() => mockSelectOne('id')} />);
    expect(getByRole('checkbox')).not.toBeChecked();
    mockSelectOne.mockImplementation(() => rerender(<Checkbox onClick={() => mockSelectOne('id')} checked />));
    userEvent.click(getByRole('checkbox'));
    expect(mockSelectOne).toBeCalledTimes(1);
    expect(mockSelectOne).toBeCalledWith('id');
    expect(getByRole('checkbox')).toBeChecked();
  });