Skip to Content
Test Stateful text input in Jest with fireEvent

Test Stateful text input in Jest with fireEvent

Looking for a quick start guide to test a text input in Jest with fireEvent? Great! Let’s get started. This guide shows you just how to write your React Testing Library (RTL) test to test the value state of your text input by firing the onChange event with fireEvent.

If you’re looking to test a text input by typing into the input, check out our how to test a React text input with userEvent post here. This post will show you how to test a stateful React text input that uses a value prop. That post tells you how to simulate typing into the text field in a unit test.

Estimated reading time: 4 minutes

We’re using Create React App in this post because it already comes stocked with the React Testing Library capabilities we need.

Want to set up React Testing Library in a Vite project? We’ve got you covered, check this post out to learn more.

In my VS Code IDE, I’ll open my working directory and throw in the Create React App command into the terminal:

npx create-react-app my-onchange-test                   

Don’t forget to change directories into your app folder:

cd my-onchange-test 

The Text Input Component

Our component is built with Material UI’s TextField. This simple, but powerful React framework allows us to create a fully reusable form input with only a few lines of code.

Let’s first start by installing our dependencies in the VS Code terminal:

npm install @mui/material @emotion/react @emotion/styled

Next we’ll create a components folder in our src folder, and within that folder a folder titled “MyTextField”.

Inside this folder we’ll create our MyTextField.js file and enter this short code snippet below.

import React from 'react'
import { TextField } from '@mui/material'

const MyTextField = (props) => {
    const { placeholder } = props
    const [value, setValue] = React.useState('')

    return <TextField placeholder={placeholder} value={value} onChange={(e) => setValue(e.target.value)} />
}

export default MyTextField

As you can see, this component is only a few lines of code, but you can see that we are setting the value to a piece of state, and triggering the value to update when the onChange event fires.

Want to learn how to test useState in a React application with Jest? Don’t miss this post!

Note that we are updating state with the onChange event.

Note that we are passing value as a piece of state. This allows us to use useState in our app to create a “controlled” or “stateful” text input.

When we test this component, we will write one test to test the initial state and a second test to test the state of our value AFTER the onChange event has fired.

Want to set up a React app using Vite instead? Check out this post on creating a React list in minutes with Vite.

Now to test a text input in Jest with fireEvent

We’ll create our unit test file by creating a file within our MyTextField folder and titling the file “MyTextField.unit.test.tsx”

We’ll import our utilities at the top like so:

import React from 'react'
import { render, screen, fireEvent } from '@testing-library/react'
import MyTextField from './MyTextField'

Next we’ll write out a basic test to ensure the component renders initially the way we’d expect. Note that this test can be used to test our initial state (aka value=”).

describe('MyTextField', () => {
   it('tests the default props', () => {
        render(<ControlledTextField placeholder='Enter text here' />)
        const input = screen.getByPlaceholderText('Enter text here')
        expect(input).toBeInTheDocument()
        expect(input).toHaveValue('') // the initial value is an empty string
    })
})

Finally we get to the meat of this post. Below is the test code to test the state of our text input when we fire the onChange event:

        it('tests the onChange event', () => {
        render(<ControlledTextField placeholder='Enter text here' />)
        const input = screen.getByPlaceholderText('Enter text here')
        const value = 'Entered Text'
        fireEvent.change(input, {
            target: {
                value
            }
        })
        expect(input).toHaveValue('Entered Text') // the state has been updated.
    })

This second test is checking that the onChange event has been fired AND that the value (or value state) has changed. In this way we can test our controlled, or stateful, text input.

Like working with React Testing Library? Check out this post on writing accessible unit tests with RTL.

Understanding the test

  • We assign the value of the input to a constant called inputconst input = screen.getByPlaceholderText('Enter text here') .
  • We create a string value to be ‘input’ when the onChange event fires, 'Entered Text'.
  • Then we use fireEvent to trigger the change event. The sole purpose of this fireEvent function is to trigger the onChange event. Because the onChange event of our component triggers a state change, we can easily test state by asserting on the value of our text input.

And that’s it. Now we know that whenever the OnChange event fires on our input, the function we use will be called.

Photo by Stephen McFadden on Unsplash