2
votes

I'm using a recent version of create-react-app (in package.json, "react": "^17.0.1")

I'm trying to use react-test-library to test an app where checking checkboxes increments a counter. I've boiled down the problem to the most hello-world form I can manage. I've tried keyDown, click...

The text expects '2' and receives '0' :

Component file:

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

function App3() {
  const [counter, setCounter]= useState(0);
  const handleClickInCheckbox = (ev) => {
  setCounter(2)
  };

  return (
    <div className="App">
      <input type="checkbox" onChange={handleClickInCheckbox} id="chkbx" data-testid="ch1" ></input>
      <h1 data-testid="h1" >{counter}</h1>
    </div>
  );
}

export default App3;

Test file:

import React from 'react';
import { render, act,  screen, fireEvent,  getByRole} from '@testing-library/react'
import '@testing-library/jest-dom/extend-expect'
import App from '../App3'

describe ('app', () => {
      test('checking boxes should increment counter',
      ()=>  {
             act( 
                   ()=>{
                    render (<App /> );
               const ch1 =   screen.getByTestId('ch1')
               const h1 =   screen.getByTestId('h1')
               ch1.focus();
               fireEvent.keyDown(document.activeElement)
               fireEvent.keyDown(screen.getByTestId('ch1'))
                 expect(h1).toHaveTextContent('2');
                 }
                )
             }
 )
})

I tried using jest-environment-jsdom-sixteen, but that doesn't change anything In package.json:

"test": "react-scripts test --env=jest-environment-jsdom-sixteen",
1

1 Answers

1
votes

The relevant event is .click, but also you shouldn't put act around the whole test:

describe ('app', () => {
  test('checking boxes should increment counter', () => {
    render(<App />);
    const ch1 = screen.getByTestId('ch1')
    const h1 = screen.getByTestId('h1')
               
    act(() => {
      fireEvent.click(screen.getByTestId('ch1'))
    })
    
    expect(h1).toHaveTextContent('2')
  })
})

In this case it actually works without act at all, because nothing asynchronous is happening, but when you do need act it should be focused on the points where you expect the state to change.