如何在react-testing-library中的单选按钮上触发更改事件?

时间:2019-02-15 00:46:53

标签: reactjs jestjs react-testing-library

我正在转移到react-testing-library,并且不知道如何触发此事件并获取更改结果。

我尝试使用fireEvent函数触发更改,然后尝试使用rerender函数,但似乎无法正常工作。

App.js

import React, { useState } from "react";
import logo from "./logo.svg";
import "./App.css";

const options = {
  DoTheThing: 'DoTheThing',
  DoOtherThing: 'DoOtherThing',
};

function App() {
  const [action, setAction] = useState(options.DoTheThing);

  return (
    <div className="App">
      <header className="App-header">
        <form>
          <fieldset>
            <label>
              <input
                type="radio"
                name="radio1"
                value={options.DoTheThing}
                checked={action === options.DoTheThing}
                onChange={event => setAction(event.target.value)}
              />
              First
            </label>

            <label>
              <input
                type="radio"
                name="radio1"
                value={options.DoOtherThing}
                checked={action === options.DoOtherThing}
                onChange={event => setAction(event.target.value)}
              />
              Second
            </label>
          </fieldset>
        </form>
      </header>
    </div>
  );
}

export default App;

App.test.js

import React from 'react';
import { render, cleanup, fireEvent } from 'react-testing-library';
import App from './App';

afterEach(cleanup);

it('should change the value ', () => {
  const {getByLabelText, rerender } = render(<App/>);
  const second = getByLabelText(/Second/);

  fireEvent.change(second);
  rerender(<App/>);

  expect(document.forms[0].elements.radio1.value).toEqual("DoOtherThing");

});

5 个答案:

答案 0 :(得分:8)

如果您具有Material-ui的Radio Component之类的标签,则可以使用:

const labelRadio: HTMLInputElement = getByLabelText('Label of Radio');
expect(labelRadio.checked).toEqual(false);
fireEvent.click(labelRadio);
expect(androidRadio.checked).toEqual(true);

或者您可以添加https://github.com/testing-library/jest-dom个匹配器并通过以下方式进行检查:

expect(getByLabelText('Label of Radio')).not.toBeChecked();
fireEvent.click(labelRadio);
expect(getByLabelText('Label of Radio')).toBeChecked();

答案 1 :(得分:5)

截至2020年5月,使用React 16.13和react-testing-library 10.0,接受的答案无效(测试本身通过了,但实际上没有做任何有意义的事情)。

我在react-testing-library甚至React本身的文档中找不到对单选按钮的任何引用。但是,据我所知,这是一个使用Typescript的示例,可以正常工作。

import React from "react";
class State {
    radioValue: string = "one"
}
export default class RadioTest extends React.Component<{}, State>
{
    state: State = new State();

    radioClick = (event: React.MouseEvent<HTMLInputElement, MouseEvent>) => {
        this.setState({ radioValue: event.currentTarget.value });
    }

    render() {
        return (<>
            <label>
                One
                <input type="radio" name="radio" onClick={this.radioClick}
                    value="one" onChange={() => {}}
                    checked={this.state.radioValue === "one"} />
            </label>
            <label>
                Two
                <input type="radio" name="radio" onClick={this.radioClick}
                    value="two" onChange={() => {}}
                    checked={this.state.radioValue === "two"} />
            </label>
            <div>current value={this.state.radioValue}</div>
            <button onClick={() => this.setState({radioValue:"one"})}>Click</button>
        </>);
    }
}

test("radiotest", () => {
    const { getByLabelText, queryByText, getByText } = render(<RadioTest />);
    const one = getByLabelText('One') as HTMLInputElement
    const two = getByLabelText('Two') as HTMLInputElement
    expect(one).toBeChecked();
    expect(two).not.toBeChecked();
    expect(queryByText("current value=one")).toBeTruthy();
    fireEvent.click(two);
    expect(one).not.toBeChecked();
    expect(two).toBeChecked();
    expect(queryByText("current value=two")).toBeTruthy();
    fireEvent.click(getByText("Click"))
    expect(one).toBeChecked();
    expect(two).not.toBeChecked();
    expect(queryByText("current value=one")).toBeTruthy();
});

React onChange处理程序将在浏览器中运行,但不适用于react-testing-library,因为当您调用fireEvent.change()时,它们不会触发。

需要使用伪onChange处理程序来避免出现React警告:“ 如果该字段是可变的,请使用defaultChecked ”。不过,您不能使用defaultChecked,因为它会阻止您在代码中设置状态(即,单击底部的按钮不会更新收音机)

因此,总的来说,React希望您使用onChange,但react-testing-library仅适用于onClick,因此这有点不合理。

答案 2 :(得分:1)

首先,您不必致电rerender。仅当您希望组件接收其他道具时才使用rerender。参见link

每当您调用fireEvent时,该组件就会像正常应用程序中那样呈现。

触发change事件是正确的,但是必须将第二个参数与事件数据一起传递。

此示例有效:

import React from "react";
import { render, fireEvent } from "react-testing-library";

test("radio", () => {
  const { getByLabelText } = render(
    <form>
      <label>
         First <input type="radio" name="radio1" value="first" />
      </label>
      <label>
        Second <input type="radio" name="radio1" value="second" />
      </label>
    </form>
  );

  const radio = getByLabelTest('First')
  fireEvent.change(radio, { target: { value: "second" } });
  expect(radio.value).toBe('second')
});

答案 3 :(得分:1)

请从react-testing-library文档中尝试此操作,“ render”应该可以正常工作。同意@Gpx

<animate 
           xlink:href="#object"
           attributeName="fill"
           values="#FFFFF;#0000FF"
           dur="3s"
           fill="freeze"/>

<animateMotion 
           xlink:href="#object"
           dur="3s"
           fill="freeze"><mpath xlink:href="#route" /> </animateMotion>

答案 4 :(得分:-1)

我也有这项工作:

                               Covid-Patient  Dr-Nr.
City    Doctor         Type
NY      Dr. Prof. Vera Checked           yes       2
                       Checked            no       2
Arizona Dr. Martin     Ordered            no       1