0

I'm looking for the simplest solution to this problem using the popular React Testing Library. I've looked at a lot of links out there and nothing seems to fit..

Here is the component in it's simplest form below:

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

function App() {
    const [loggedIn, setLoggedIn] = useState(false)

    useEffect(() => {
        setTimeout(() => setLoggedIn(true), 1000)
      }, [])
      return (
      <button data-testid="login-button">{loggedIn ? "Log Out" : "Log In"}</button>
      );
}
export default App;

And below is the test for the 'no wait' state of the button but would like to know how to implement 'waitFor' within the same test for the change in text in the button after 1 second..

import { render, screen, waitFor } from "@testing-library/react";
import App from "./App";
test('Check the text "Log out" is eventually there', () => {
    render(<App />);
    const LoginButton = screen.getByText(/Log/)
    expect(LoginButton).toHaveTextContent(/Log In/i);
    /*How to use waitFor here*/
});

I know we can mock the return from an API call easily and for this problem we probably have to return a promise before we can test using 'waitFor'. How can we use 'WaitFor' in the example test file above?

2 Answers 2

1

You can use jest's Timer Mocks to handle the setTimeouts.

import { act, render, screen } from "@testing-library/react";
import App from "./App";

test("renders learn react link", () => {
  // use the fake timer
  jest.useFakeTimers();
  render(<App />);

  // assert the initial text of the button
  expect(screen.getByRole("button", { name: "Log In" })).toBeInTheDocument();

  // advance the timer
  act(() => jest.advanceTimersByTime(1000));

  // assert the changed text of the button
  expect(screen.getByRole("button", { name: "Log Out" })).toBeInTheDocument();

  // switch back to use real timers
  jest.useRealTimers();
});

Reference:

Using act() for timers

Sign up to request clarification or add additional context in comments.

Comments

0

Thankyou Shyam for helping me discover the solution, which was not using 'waitFor' from the testing-library in this case:

test('Check the text "Log out" is eventually there', () => {

jest.useFakeTimers();

render();

//Reference the element by locating using Regex

const LoginButton = screen.getByText(/Log/);

//Search in real time for the initial/default text on the button

expect(LoginButton).toHaveTextContent(/Log In/i);

// advance the timer

act(() => jest.advanceTimersByTime(1000));

// assert the changed text of the button

expect(LoginButton).toHaveTextContent(/Log Out/i);

// switch back to use real timers

jest.useRealTimers();

});

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.