testing select element in react with Jest

10,698

Solution 1

I suggest you to use the userEvent from the React Testing Library.

It's very straightforward and simple to use. Here is the provided example:

import React from "react";
import { render } from "@testing-library/react";
import userEvent from "@testing-library/user-event";

test("select values", () => {
    const { getByTestId } = render(
        <select multiple data-testid="select-multiple">
            <option data-testid="val1" value="1">
                1
            </option>
            <option data-testid="val2" value="2">
                2
            </option>
            <option data-testid="val3" value="3">
                3
            </option>
        </select>
    );

    userEvent.selectOptions(getByTestId("select-multiple"), ["1", "3"]);

    expect(getByTestId("val1").selected).toBe(true);
    expect(getByTestId("val2").selected).toBe(false);
    expect(getByTestId("val3").selected).toBe(true);
});

Solution 2

I found a way to do this using Simulate from react-dom test-utils.

import React from "react";
import { render, unmountComponentAtNode } from "react-dom";
import { act, Simulate } from "react-dom/test-utils";

test("Should change preference", () => {
    act(() => {
        render(<TestSelect/>, container);
    });
    let message = container.querySelector("h4");
    expect(message.innerHTML).toContain("apples");
    const selectElement = container.querySelector("select");
    act(() => {
        Simulate.change(selectElement, { target: { value: "oranges" }});
    });
    message = container.querySelector("h4");
    expect(message.innerHTML).toContain("oranges");
});
Share:
10,698

Related videos on Youtube

Adam D
Author by

Adam D

I love open source, collaboration, and thinking about how software can help language learning.

Updated on June 04, 2022

Comments

  • Adam D
    Adam D about 2 years

    I am trying to test functionality of a select element in a React component.

    Note: This is not a duplicate of this question because I am not using enzyme, but rather trying to do things simply using act() from React's Test Utilities and running tests with Jest.

    Given a component with a select element like this:

    class TestSelect extends React.Component {
        constructor(props) {
            super(props);
            this.state = {
                choice: "apples",
            };
            this.handleChange = this.handleChange.bind(this);
        }
        handleChange(event) {
            this.setState({choice: event.target.value});
        }
        render() {
            return (
                <div>
                    <select value={this.state.choice} onChange={this.handleChange}>
                        <option value="apples">apples</option>
                        <option value="oranges">oranges</option>
                    </select>
                    <h4>You like {this.state.choice}</h4>
                </div>
            );
        }
    }
    

    I would like to be able to test it like this:

    import React from "react";
    import { render, unmountComponentAtNode } from "react-dom";
    import { act } from "react-dom/test-utils";
    
    test("Should change preference", () => {
        act(() => {
            render(<TestSelect/>, container);
        });
        let message = container.querySelector("h4");
        expect(message.innerHTML).toContain("apples");
        const selectElement = container.querySelector("select");
        act(() => {
            selectElement.dispatchEvent(new Event("change"), {
                target: { value: "oranges"},
                bubbles: true,
            });
        });
        message = container.querySelector("h4");
        // Test fails here: Value does not change
        expect(message.innerHTML).toContain("oranges");
    });
    

    After a lot of fiddling and trying different options I am not able to simulate an event that ends up changing the selected value in the select element.