Reputation: 33
I am having some trouble to test simple navigation,
I have a react app using react-router-dom and the App component is wrapped with suspense.
I also import my components dynamically to be able to code split.
For some reason, in the unit test when I trigger a click on the nav About link from the homepage.
it always renders the 404 NotFound components and never the about Component, which exists
What do I do wrong?
Main.js
const Main = () => <h1>Home page</h1>;
About.js
const About = () => <h1>About page</h1>;
NotFound.js
const NotFound = () => <div>404 this page does not exist</div>;
Nav.js
const Nav = () => (
<div className="dummy-nav">
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/about">About</Link>
</li>
</ul>
</div>
);
App.js
import React, { Component, Suspense, lazy } from "react";
import { Switch, Route } from "react-router-dom";
import Nav from "./Nav";
const Main = lazy(() => import(/* webpackChunkName: "Main" */ "./Main"));
const About = lazy(() => import(/* webpackChunkName: "About" */ "./About"));
const NotFound = lazy(() =>
import(/* webpackChunkName: "About" */ "./NotFound")
);
class App extends Component {
render() {
return (
<Suspense fallback={<div>Loading...</div>}>
<div>This is the App</div>
<Nav />
<Switch>
<Route exact path="/" component={Main} />
<Route path="/about" component={About} />
<Route render={() => <NotFound />} />
</Switch>
</Suspense>
);
}
}
app.test.js
function renderWithRouter(
ui,
{
route = "/",
history = createMemoryHistory({ initialEntries: [route] }),
...renderOptions
} = {}
) {
// eslint-disable-next-line react/prop-types
function Wrapper({ children }) {
return <Router history={history}>{children}</Router>;
}
return {
...render(ui, { wrapper: Wrapper, ...renderOptions }),
history
};
}
test("renders homepage by default and can navigate to about", async () => {
renderWithRouter(<App />);
screen.getByText(/Home page/i);
const link = screen.getByRole("link", { name: /About/i });
userEvent.click(link);
await waitFor(() => screen.getByText(/About page/i));
screen.debug();
});
Here is a code sandbox with the broken test and the app structure that I am using, If you have any tips to use and test lazy and dynamic import, please share
https://codesandbox.io/s/react-router-suspense-lrnp7?file=/src/App.js
Upvotes: 1
Views: 1977
Reputation: 501
You should use react-router-dom v6
if you want to use history v5.x
.
https://www.npmjs.com/package/history
Upvotes: 0
Reputation: 33
I finally found what is going wrong but I don’t fully understand why.
The issue was the use of the latest version of the History package 5.0.0.
broken example => https://codesandbox.io/s/history-v50-always-render-404-after-usereventclick-h8osi?file=/src/tests/test.js
Downgrading to the previous version 4.10.1 fixes the issue. that is, any click on a Link will result to render the 404-page or nothing.
Working example with History 4.10.1 => https://codesandbox.io/s/history-v4101-fix-404-madness-4uitj?file=/src/tests/react-router.js:413-451
After looking at what changes in the latest History version,
I don’t see any breaking change or any obvious reason why that should happen.
Any idea of why that happens and how to use correctly the latest history??
If you get in this 404 madness, look at of your history version.
Upvotes: 0