import React from'react'import{ render }from'@testing-library/react'import{
Router,
Link,
createHistory,
createMemorySource,
LocationProvider,}from'@reach/router'import'@testing-library/jest-dom/extend-expect'constAbout=()=><div>You are on the about page</div>constHome=()=><div>You are home</div>constNoMatch=()=><div>No match</div>functionApp(){return(<div><Linkto="/">Home</Link><Linkto="/about">About</Link><Router><Homepath="/"/><Aboutpath="/about"/><NoMatchdefault/></Router></div>)}// Ok, so here's what your tests might look like// this is a handy function that I would utilize for any component// that relies on the router being in contextfunctionrenderWithRouter(
ui,{ route ='/', history =createHistory(createMemorySource(route))}={}){return{...render(<LocationProviderhistory={history}>{ui}</LocationProvider>),// adding `history` to the returned utilities to allow us// to reference it in our tests (just try to avoid using// this to test implementation details).
history,}}test('full app rendering/navigating',async()=>{const{
container,
history:{ navigate },}=renderWithRouter(<App/>)const appContainer = container
// normally I'd use a data-testid, but just wanted to show this is also possibleexpect(appContainer.innerHTML).toMatch('You are home')// with reach-router we don't need to simulate a click event, we can just transition// to the page using the navigate function returned from the history object.awaitnavigate('/about')expect(container.innerHTML).toMatch('You are on the about page')})test('landing on a bad page',()=>{const{ container }=renderWithRouter(<App/>,{
route:'/something-that-does-not-match',})// normally I'd use a data-testid, but just wanted to show this is also possibleexpect(container.innerHTML).toMatch('No match')})// If your route component has parameters, you'll have to change the render function a little bit// example of a route component with parameterconstRoutes=()=>(<Router><SomeComponentpath="/some-component/:id"/></Router>)// render function with Router wrapper from @reach/routerfunctionrenderWithRouterWrapper(
ui,{ route ='/', history =createHistory(createMemorySource(route))}={}){return{...render(<LocationProviderhistory={history}><Router>{ui}</Router></LocationProvider>),
history,}}test('renders the component with params',()=>{// you'll have to declare the path prop in the component, exactly like the routerenderWithRouterWrapper(<SomeComponentpath="/some-component/:id"/>,{// and pass the parameter value on the route config
route:'/some-component/1',})})