Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can't get MemoryRouter to work with @testing-library/react

I'm trying to test that my router is working as expected. But I can't get the router to point to another location than /

Here's my simplified test code.

App.tsx

import React from 'react';
import {Route, Switch, BrowserRouter} from 'react-router-dom';

const App: React.FC = () => {
    return (
        <div>
            <BrowserRouter>
                <Switch>
                    <Route path={'/test'}>test</Route>
                    <Route path={'/'}>index</Route>
                </Switch>
            </BrowserRouter>
        </div>
    );
};

export default App;

App.test.tsx

import React from 'react';
import App from './App';
import {MemoryRouter} from 'react-router-dom';
import {render} from '@testing-library/react';


test('renders /test route', async () => {
    const app = render(
        <MemoryRouter initialEntries={['/test']} initialIndex={0}>
            <App/>
        </MemoryRouter>);
    expect(app.getByText(/test/i)).toBeInTheDocument();
});

I get the following error message

Error: Unable to find an element with the text: /test/i. 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>
       index
    </div>
  </div>
</body>

What am I doing wrong?

like image 347
emcell Avatar asked Jan 24 '20 07:01

emcell


People also ask

How do I enable the button in react test library?

Use data-test-id for <button> element. Select one of the ancestors of the <Click /> component and then select the button within(...) this scope. Click on the selected element with fireEvent and check that nothing has happened.

Do I need to use ACT WITH react testing library?

You don't need to use act() actually. The reason why you don't need to do is the most of cases like userEvent, render are wrapped in act already. eventWrapper() in testing-library/dom is called when event functions like userEvent. click are invoked to make changes to jsdom.


1 Answers

The problem is, that the component I wanted to test already has a router declared. To solve this issue I had to split up the App Component into App and Routes.

For the testing I just have to render the Routes component and everything works as expected.

App.tsx

import React from 'react';
import {Route, Switch, BrowserRouter} from 'react-router-dom';

export const Routes = () => {
    return (
        <>
            <Switch>
                <Route path={'/test'}> test</Route>
                <Route path={'/'}> index</Route>
            </Switch>
        </>
    )
};

const App: React.FC = () => {
    return (
        <div>
            <BrowserRouter>
                <Routes/>
            </BrowserRouter>
        </div>
    );
};

export default App;

App.test.tsx

import React from 'react';
import {Routes} from './App';
import {MemoryRouter} from 'react-router-dom';
import {render} from '@testing-library/react';


test('renders routes correct', async () => {
    const app = render(
        <MemoryRouter initialEntries={['/test']} initialIndex={0}>
            <Routes/>
        </MemoryRouter>
    );
    expect(app.getByText(/test/i)).toBeInTheDocument();
});

like image 117
emcell Avatar answered Oct 23 '22 19:10

emcell