J'essaie de tester que mon routeur fonctionne comme prévu. Mais je n'arrive pas à faire pointer le routeur vers un autre emplacement que /

Voici mon code de test simplifié.

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();
});

Je reçois le message d'erreur suivant

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>

Qu'est-ce que je fais mal?

12
emcell 24 janv. 2020 à 10:45

2 réponses

Meilleure réponse

Le problème est que le composant que je voulais tester a déjà un routeur déclaré. Pour résoudre ce problème, j'ai dû diviser le composant App en App et Routes.

Pour les tests, je dois juste rendre le composant Routes et tout fonctionne comme prévu.

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();
});

7
emcell 24 janv. 2020 à 11:18

Si vous chargez App à partir de index.js, ce qui était le cas lorsque je rencontrais ce problème sur une application Create React App, vous pouvez également envelopper App dans un Router là, puis testez les routes App comme vous vous en doutez sans avoir à exporter Routes comme vous l'avez fait.

Par exemple (sinon une action CRA index.js) :

// index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter as Router } from 'react-router-dom';
import './index.css';
import App from './app';
import * as serviceWorker from './serviceWorker';

ReactDOM.render(
  <React.StrictMode>
    <Router>
      <App />
    </Router>
  </React.StrictMode>,
  document.getElementById('root')
);

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
serviceWorker.unregister();
0
Derek 11 déc. 2020 à 21:58