Using react testing-library to manipulate DOM in React App

142 Views Asked by At

I'm building some custom dev tools inspired by this Kent C Dodds post and trying to automatically fill in some values for a form I've created.

I have an button that triggers this function where I'm trying fill in an input box. Going off his suggestion to use some utilities from @testing-library/react I thought this should be possible.

  • Is there something wrong with my code?
  • Is this even possible? I tried manipulating the DOM directly, but it's a Material UI input and that was also not behaving as expected.
import { screen, fireEvent } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

async function FillOutForm() {
    // const user = userEvent.setup(); // tried this on and off but didn't seem to matter

    const uploadButton = screen.getByRole('button', { name: /upload/i });
    uploadButton.click();

    //await for upload modal to open
    await screen.findByRole('dialog');

    const input = await screen.findByLabelText('Name');
    console.log('input', { input }); //works, it found the value

   
    // userEvent.type(input, 'test'); //freezes, no input filled

    // await user.type(input, 'test'); //freezes, no input filled

    // await act(async () => userEvent.type(await input, 'some text')); //fills in the text, but freezes after and gives an error
   console.log('i never get here?');
}

Edit: This appears to be specific to styled components or Material UI. When I use a vanilla input, userEvent.type seems to work just fine.

Edit #2: Here's a repro in stack blitz - at least for some freezing behavior.

Uncomment this line to see some type of infinite loop get kicked off.

    // userEvent.click(button) //uncomment to see what causes freeze - some type of infinite loop?

https://stackblitz.com/edit/react18-mui-fsezub?file=App.tsx

2

There are 2 best solutions below

0
colinwurtz On BEST ANSWER

It turns out I had an infinitely rendering component behind the form I was using. It allowed me to interact fine with the form when typing manually, but chaos ensued when I brought in react testing library.

Turns out this is a completely valid use case/approach and works now after I fixed that infinite loop problem.

2
harsh Kanodiya On

There might be an issue with how you are using the useEvent library try the below code and see if it works or not

import { screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

async function FillOutForm() {
const uploadButton = screen.getByRole('button', { name: /upload/i });
userEvent.click(uploadButton);

// Wait for the upload modal to open, assuming there's a loading indicator 
 or some asynchronous behavior
await screen.findByRole('dialog');

const input = screen.getByLabelText('Name');
console.log('input', { input }); // works, it found the input

// Use userEvent.type to enter text into the input field
userEvent.type(input, 'test');

console.log('I get here!');
}

export default FillOutForm;