Skip to content

Latest commit

 

History

History
216 lines (165 loc) · 5.41 KB

example-react-router.mdx

File metadata and controls

216 lines (165 loc) · 5.41 KB
idtitle
example-react-router
React Router

This example demonstrates React Router v6. For previous versions see below.

// app.jsimportReactfrom'react'import{Link,Route,Routes,useLocation}from'react-router-dom'constAbout=()=><div>You are on the about page</div>constHome=()=><div>You are home</div>constNoMatch=()=><div>No match</div>exportconstLocationDisplay=()=>{constlocation=useLocation()return<divdata-testid="location-display">{location.pathname}</div>}exportconstApp=()=>(<div><Linkto="/">Home</Link><Linkto="/about">About</Link><Routes><Routepath="/"element={<Home/>}/><Routepath="/about"element={<About/>}/><Routepath="*"element={<NoMatch/>}/></Routes><LocationDisplay/></div>)
// app.test.jsimport{render,screen}from'@testing-library/react'importuserEventfrom'@testing-library/user-event'importReactfrom'react'import'@testing-library/jest-dom'import{App,LocationDisplay}from'./app'import{BrowserRouter,MemoryRouter}from'react-router-dom'test('full app rendering/navigating',async()=>{render(<App/>,{wrapper: BrowserRouter})constuser=userEvent.setup()// verify page content for default routeexpect(screen.getByText(/youarehome/i)).toBeInTheDocument()// verify page content for expected route after navigatingawaituser.click(screen.getByText(/about/i))expect(screen.getByText(/youareontheaboutpage/i)).toBeInTheDocument()})test('landing on a bad page',()=>{constbadRoute='/some/bad/route'// use <MemoryRouter> when you want to manually control the historyrender(<MemoryRouterinitialEntries={[badRoute]}><App/></MemoryRouter>,)// verify navigation to "no match" routeexpect(screen.getByText(/nomatch/i)).toBeInTheDocument()})test('rendering a component that uses useLocation',()=>{constroute='/some-route'// use <MemoryRouter> when you want to manually control the historyrender(<MemoryRouterinitialEntries={[route]}><LocationDisplay/></MemoryRouter>,)// verify location display is renderedexpect(screen.getByTestId('location-display')).toHaveTextContent(route)})

Reducing boilerplate

  1. If you find yourself adding Router components to your tests a lot, you may want to create a helper function that wraps around render.
// test utils fileconstrenderWithRouter=(ui,{route ='/'}={})=>{window.history.pushState({},'Test page',route)return{user: userEvent.setup(), ...render(ui,{wrapper: BrowserRouter}),}}
// app.test.jstest('full app rendering/navigating',async()=>{const{user}=renderWithRouter(<App/>)expect(screen.getByText(/youarehome/i)).toBeInTheDocument()awaituser.click(screen.getByText(/about/i))expect(screen.getByText(/youareontheaboutpage/i)).toBeInTheDocument()})test('landing on a bad page',()=>{renderWithRouter(<App/>,{route: '/something-that-does-not-match'})expect(screen.getByText(/nomatch/i)).toBeInTheDocument()})test('rendering a component that uses useLocation',()=>{constroute='/some-route'renderWithRouter(<LocationDisplay/>,{route})expect(screen.getByTestId('location-display')).toHaveTextContent(route)})

Testing Library and React Router v5

// app.jsimportReactfrom'react'import{Link,Route,Switch,useLocation}from'react-router-dom'constAbout=()=><div>You are on the about page</div>constHome=()=><div>You are home</div>constNoMatch=()=><div>No match</div>exportconstLocationDisplay=()=>{constlocation=useLocation()return<divdata-testid="location-display">{location.pathname}</div>}exportconstApp=()=>(<div><Linkto="/">Home</Link><Linkto="/about">About</Link><Switch><Routeexactpath="/"component={Home}/><Routepath="/about"component={About}/><Routecomponent={NoMatch}/></Switch><LocationDisplay/></div>)

In your tests, pass the history object as a whole to the Router component. Note: React Router v5 only works with History v4, so make sure you have the correct version of history installed.

// app.test.jsimport{render,screen}from'@testing-library/react'importuserEventfrom'@testing-library/user-event'import{createMemoryHistory}from'history'importReactfrom'react'import{Router}from'react-router-dom'import'@testing-library/jest-dom'import{App}from'./app'// React Router v5test('full app rendering/navigating',async()=>{consthistory=createMemoryHistory()render(<Routerhistory={history}><App/></Router>,)constuser=userEvent.setup()// verify page content for expected route// often you'd use a data-testid or role query, but this is also possibleexpect(screen.getByText(/youarehome/i)).toBeInTheDocument()awaituser.click(screen.getByText(/about/i))// check that the content changed to the new pageexpect(screen.getByText(/youareontheaboutpage/i)).toBeInTheDocument()})test('landing on a bad page',()=>{consthistory=createMemoryHistory()history.push('/some/bad/route')render(<Routerhistory={history}><App/></Router>,)expect(screen.getByText(/nomatch/i)).toBeInTheDocument()})
close