0

** Unable to find an element by: [data-testid="reload-button"]**

Facing issues when testing a create-react-app using RTL.

I've a simple react project wherein I'm making a call over the internet to display a list of users. While writing a testcase for the same, I'm trying to mock a fetch call and provide dummy data as well so that my app doesn't increase load on the server.

But I'm facing issues in this.

I get an error saying:

`Unable to find an element by: [data-testid="reload-button"]

Ignored nodes: comments, script, style
<body>
  <div />
</body>

  15 |     render(<Body  />)
  16 |
> 17 |     await waitFor(()=>expect(screen.getByTestId("reload-button")))
     |                  ^
  18 |     const usersArray = screen.getAllByTestId("users-list")
  19 |     expect(usersArray.length).toBe(5)
  20 | })

  at waitForWrapper (node_modules/@testing-library/react/node_modules/@testing-library/dom/dist/wait-for.js:166:27)
  at Object.<anonymous> (src/components/__tests___/Body.test.js:17:18)`

My code is as follows:

The component where an api call is made, using which the state is changed and data is passed on to the as props

//Body.js

const Body = () => {
    const [ users, setUsers ] = useState([])
    const  [ reloadUsers , setReloadUsers] = useState(false)
    useEffect(() =>{
        fetchUsers()
    },[reloadUsers])

    const fetchUsers = async () => {
        const data = await fetch(`https://randomuser.me/api/?results=5`) 
        const jsonData = await data.json()
        setUsers(jsonData?.results)
    }
    if(!users)return null

    return users.length===0 ? <p>Loading...</p> :  (
        <div>
            <button 
               data-testid='reload-button' 
               onClick={()=> setReloadUsers(prev => !prev) } >
               Load different users
            </button>
            <UserList users={users}  />
        </div>
      )
}

The component receiveing the data as props and then mapping over it to display the data

//UserList.js

const UserList = ({users}) => {
    const displayList = users.map(user=>(
        <li data-testid="users-list"  
            style={{'display' : 'flex' , 'alignItems' : 'center' , 'margin' : '20px'}}  
            key={user?.login?.uuid} 
        >
            <img  
              style={{'borderRadius':'30px' , 'marginRight' : '20px'}} 
              src={user?.picture?.thumbnail} alt='thumbnail'  />
            <span>{user?.name?.first} {user?.name?.last} </span>
        </li>
    ))
  return (
    <div>
        <h5>UserList</h5>
        <ul style={{ 'listStyleType' : 'none' }} >
            {displayList}
        </ul>
    </div>
  )
}


My test file is as follows where I'm testing if the mock data is getting populated

//Body.test.js

import { render, screen, waitFor } from "@testing-library/react"
import Body from "../Body"
import { usersList } from "../utils/constants";

test('user list should appear on screen', async ()=>{

    global.fetch = jest.fn(()=>{
        return Promise.resolve({
            json : () => {
                return Promise.resolve(usersList)
            }
        })
    })

    render(<Body  />)

    await waitFor(()=>expect(screen.getByTestId("reload-button")))
    const usersArray = screen.getAllByTestId("users-list")
    expect(usersArray.length).toBe(5)
})

What is the mistake that I'm doing?

2
  • Have you checked out: stackoverflow.com/questions/67653566/…? Commented Jun 3, 2023 at 3:03
  • Yes, I did see this. In my case, I've a strong feeling that the issue is due to async calls Commented Jun 3, 2023 at 13:36

1 Answer 1

0

It's probably because the mock resolved data you provided is not correct. The data structure should be: { results: [] }. Then, everything works fine.

e.g.

Body.test.tsx:

import React from 'react';
import { render, screen, waitFor } from '@testing-library/react';
import '@testing-library/jest-dom';
import { Body } from './Body';

test('user list should appear on screen', async () => {
  (global as any).fetch = jest.fn(() => {
    return Promise.resolve({
      json: () => {
        return Promise.resolve({
          results: [
            { name: { first: 'first1', last: 'last1' }, login: { uuid: 1 } },
            { name: { first: 'first2', last: 'last2' }, login: { uuid: 2 } },
            { name: { first: 'first3', last: 'last3' }, login: { uuid: 3 } },
            { name: { first: 'first4', last: 'last4' }, login: { uuid: 4 } },
            { name: { first: 'first5', last: 'last5' }, login: { uuid: 5 } },
          ],
        });
      },
    });
  });

  render(<Body />);

  await waitFor(() => expect(screen.getByTestId('reload-button')).toBeInTheDocument());
  const usersArray = screen.getAllByTestId('users-list');
  expect(usersArray.length).toBe(5);
});

Test result:

 PASS  stackoverflow/76394391/Body.test.tsx
  √ user list should appear on screen (49 ms)
                                                                                                                                                                                                 
Test Suites: 1 passed, 1 total                                                                                                                                                                   
Tests:       1 passed, 1 total                                                                                                                                                                   
Snapshots:   0 total
Time:        1.112 s
Ran all test suites related to changed files.
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.