I'm in the process of moving over to react-testing-library, and have no idea how to trigger this event and get the results of the changes.
I've tried using the fireEvent
function to trigger the change, and then tried the rerender
function, but I can't seem to get it to work.
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");
});
Update
As people pointed out my original solution was wrong.
Nowadays I suggest you use userEvent
for better-simulating user interactions.
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
test("radio", () => {
const user = userEvent.setup();
render(
<form>
<label>
First <input type="radio" name="radio1" value="first" />
</label>
<label>
Second <input type="radio" name="radio1" value="second" />
</label>
</form>
)
await user.click(screen.getByLabelText("Second"));
});
First, you don't have to call rerender
. You use rerender
only when you want the component to receive different props. See link.
Whenever you call fireEvent
the component will render like it would in your normal app.
It's correct to fire a change
event, but you must pass a second parameter with the event data.
This example works:
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 = getByLabelText('First')
fireEvent.change(radio, { target: { value: "second" } });
expect(radio.value).toBe('second')
});