React redirect unit test not rendering expected dom

I am trying to unit test (with React Testing Library) that my redirect occurs as expected and as actually occurs in practise, however it doesn’t seem that anything is actually being rendered in my test…


App.js

// I set up a test route to get this working before I point it at the real page

<Route exact path={`${process.env.PUBLIC_URL}/blah`} render={() => (
    <div data-testid="my-test">THIS IS A TEST</div>
)}/>

MyComponent.jsx

// I have forced this component to do the redirect for testing purposes
...
return (
    <BrowserRouter>
        <Redirect to={`${process.env.PUBLIC_URL}/blah`} />
    </BrowserRouter>
);

I found that not wrapping my <Redirect> in <BrowserRouter> would yield the error

You should not use <Redirect> outside a <Router>

Test.js

it('should redirect', async () => {
    const state = configState(); // <---- Set custom initial state of component
    const store = configureStore();

    rendered = render(
        <Provider store={store(state)}>
            <ForgotPasswordNewPasswordJourney />
        </Provider>
    );

    // check that the content changed to the new page
    expect(rendered.getByText("THIS IS A TEST")).toBeTruthy();
});

The result of this test is:

TestingLibraryElementError: Unable to find an element with the text: THIS IS A TEST. 
This could be because the text is broken up by multiple elements. 
In this case, you can provide a function for your text matcher to make your matcher more flexible.

<body>
   <div />
   <div />
</body>

      116 | 
      117 |         // check that the content changed to the new page
    > 118 |         expect(rendered.getByText("THIS IS A TEST")).toBeTruthy();
          |                         ^
      119 |     });
      120 | 
      121 | 

Note: I get this error also when I wrap my test render with a <BrowserRouter> also:

<Provider store={store(state)}>
    <BrowserRouter>
         <ForgotPasswordNewPasswordJourney />
    </BrowserRouter>
</Provider>

Peculiar behaviour…
I did read online that maybe it was an async/await issue as the redirect will take time to perform etc. So I saw that using waitFor may be an option, and when performing:

waitFor(() => expect(rendered.getByText("THIS IS A TEST")).toBeTruthy());

this actually passed the test to my surprise… However, if I then put a nonsense string in the getByText field, this would also pass my test… So it seems that this also isn’t the answer.

What am I doing wrong?

2 thoughts on “React redirect unit test not rendering expected dom”

  1. I managed to solve this after viewing this article and I could see my mistake.

    It appears that I was required to add a <Router and <Route within my <Provider> as a kind of mock route to go through.

    const myStore = configureStore();
    const history = createMemoryHistory();
    history.push(fromUrl);
    
    <Provider store={myStore(store)}>
       <Router history={myHistory}>
           <Component {...props} />
           <Route path={toUrl}>
               <div data-testid="test">THIS IS A TEST</div>
           </Route>
       </Router>
    </Provider>
    

    I could then start to see things being rendered in the test.

    It is also possible to actually render a component rather than a test element:

    <Route path={toUrl}> render={() => <RedirectComponent {...props} />}
    

    however if this is with Redux, we will be required to add the <Provider> and store wrapper around this also.

    Reply

Leave a Comment