Skip to content

Commit 783fbb3

Browse files
Update example-react-router.md (#622)
1 parent 911abe8 commit 783fbb3

File tree

1 file changed

+79
-65
lines changed

1 file changed

+79
-65
lines changed

docs/example-react-router.md

Lines changed: 79 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -6,99 +6,116 @@ title: React Router
66
```jsx
77
// app.js
88
import React from 'react'
9-
import { withRouter } from 'react-router'
109
import { Link, Route, Switch } from 'react-router-dom'
1110

12-
const About = () => <h1>You are on the about page</h1>
13-
const Home = () => <h1>You are home</h1>
14-
const NoMatch = () => <h1>404 Not Found</h1>
15-
16-
const LocationDisplay = withRouter(({ location }) => (
17-
<div data-testid="location-display">{location.pathname}</div>
18-
))
19-
20-
function App() {
21-
return (
22-
<div>
23-
<Link to="/">Home</Link>
24-
<Link to="/about">About</Link>
25-
<Switch>
26-
<Route exact path="/" component={Home} />
27-
<Route path="/about" component={About} />
28-
<Route component={NoMatch} />
29-
</Switch>
30-
<LocationDisplay />
31-
</div>
32-
)
11+
const About = () => <div>You are on the about page</div>
12+
const Home = () => <div>You are home</div>
13+
const NoMatch = () => <div>No match</div>
14+
15+
export const LocationDisplay = () => {
16+
const location = useLocation()
17+
18+
return <div data-testid="location-display">{location.pathname}</div>
3319
}
3420

35-
export { LocationDisplay, App }
21+
export const App = () => (
22+
<div>
23+
<Link to="/">Home</Link>
24+
25+
<Link to="/about">About</Link>
26+
27+
<Switch>
28+
<Route exact path="/">
29+
<Home />
30+
</Route>
31+
32+
<Route path="/about">
33+
<About />
34+
</Route>
35+
36+
<Route>
37+
<NoMatch />
38+
</Route>
39+
</Switch>
40+
41+
<LocationDisplay />
42+
</div>
43+
)
3644
```
3745

3846
```jsx
3947
// app.test.js
48+
import { render, screen } from '@testing-library/react'
49+
import userEvent from '@testing-library/user-event'
50+
import { createMemoryHistory } from 'history'
4051
import React from 'react'
4152
import { Router } from 'react-router-dom'
42-
import { createMemoryHistory } from 'history'
43-
import { render, fireEvent } from '@testing-library/react'
53+
4454
import '@testing-library/jest-dom/extend-expect'
45-
import { LocationDisplay, App } from './app'
55+
56+
import { App, LocationDisplay } from './app'
4657

4758
test('full app rendering/navigating', () => {
4859
const history = createMemoryHistory()
49-
const { container, getByText } = render(
60+
render(
5061
<Router history={history}>
5162
<App />
5263
</Router>
5364
)
5465
// verify page content for expected route
5566
// often you'd use a data-testid or role query, but this is also possible
56-
expect(container.innerHTML).toMatch('You are home')
67+
expect(screen.getByText(/you are home/i)).toBeInTheDocument()
5768

58-
fireEvent.click(getByText(/about/i))
69+
const leftClick = { button: 0 }
70+
userEvent.click(screen.getByText(/about/i), leftClick)
5971

6072
// check that the content changed to the new page
61-
expect(container.innerHTML).toMatch('You are on the about page')
73+
expect(screen.getByText(/you are on the about page/i)).toBeInTheDocument()
6274
})
6375

64-
test('landing on a bad page shows 404 page', () => {
76+
test('landing on a bad page', () => {
6577
const history = createMemoryHistory()
6678
history.push('/some/bad/route')
67-
const { getByRole } = render(
79+
render(
6880
<Router history={history}>
6981
<App />
7082
</Router>
7183
)
72-
expect(getByRole('heading')).toHaveTextContent('404 Not Found')
84+
85+
expect(screen.getByText(/no match/i)).toBeInTheDocument()
7386
})
7487

75-
test('rendering a component that uses withRouter', () => {
88+
test('rendering a component that uses useLocation', () => {
7689
const history = createMemoryHistory()
7790
const route = '/some-route'
7891
history.push(route)
79-
const { getByTestId } = render(
92+
render(
8093
<Router history={history}>
8194
<LocationDisplay />
8295
</Router>
8396
)
84-
expect(getByTestId('location-display')).toHaveTextContent(route)
97+
98+
expect(screen.getByTestId('location-display')).toHaveTextContent(route)
8599
})
86100
```
87101

88102
## Reducing boilerplate
89103

90104
1. You can use the `wrapper` option to wrap a `MemoryRouter` around the
91-
component you want to render (`MemoryRouter` works when you don't need access
92-
to the history object itself in the test, but just need the components to be
93-
able to render and navigate).
105+
component you want to render.
106+
`MemoryRouter` works when you don't need access to the history object itself
107+
in the test, but just need the components to be able to render and
108+
navigate.
109+
If you _do_ need to change the history, you could use `BrowserRouter`.
94110

95111
```jsx
96112
import { MemoryRouter } from 'react-router-dom'
97113

98114
test('full app rendering/navigating', () => {
99-
const { container, getByText } = render(<App />, { wrapper: MemoryRouter })
115+
render(<App />, { wrapper: MemoryRouter })
116+
100117
// verify page content for expected route
101-
expect(getByRole('heading')).toMatch('Home')
118+
expect(screen.getByText(/you are home/i)).toBeInTheDocument()
102119
})
103120
```
104121

@@ -107,38 +124,35 @@ test('full app rendering/navigating', () => {
107124

108125
```jsx
109126
// test utils file
110-
function renderWithRouter(
111-
ui,
112-
{
113-
route = '/',
114-
history = createMemoryHistory({ initialEntries: [route] }),
115-
} = {}
116-
) {
117-
const Wrapper = ({ children }) => (
118-
<Router history={history}>{children}</Router>
119-
)
120-
return {
121-
...render(ui, { wrapper: Wrapper }),
122-
// adding `history` to the returned utilities to allow us
123-
// to reference it in our tests (just try to avoid using
124-
// this to test implementation details).
125-
history,
126-
}
127+
const renderWithRouter = (ui, { route = '/' } = {}) => {
128+
window.history.pushState({}, 'Test page', route)
129+
130+
return render(ui, { wrapper: BrowserRouter })
127131
}
128132
```
129133

130134
```jsx
131135
// app.test.js
136+
test('full app rendering/navigating', () => {
137+
renderWithRouter(<App />)
138+
expect(screen.getByText(/you are home/i)).toBeInTheDocument()
139+
140+
const leftClick = { button: 0 }
141+
userEvent.click(screen.getByText(/about/i), leftClick)
142+
143+
expect(screen.getByText(/you are on the about page/i)).toBeInTheDocument()
144+
})
145+
132146
test('landing on a bad page', () => {
133-
const { container } = renderWithRouter(<App />, {
134-
route: '/something-that-does-not-match',
135-
})
136-
expect(container.innerHTML).toMatch('No match')
147+
renderWithRouter(<App />, { route: '/something-that-does-not-match' })
148+
149+
expect(screen.getByText(/no match/i)).toBeInTheDocument()
137150
})
138151

139-
test('rendering a component that uses withRouter', () => {
152+
test('rendering a component that uses useLocation', () => {
140153
const route = '/some-route'
141-
const { getByTestId } = renderWithRouter(<LocationDisplay />, { route })
142-
expect(getByTestId('location-display')).toHaveTextContent(route)
154+
renderWithRouter(<LocationDisplay />, { route })
155+
156+
expect(screen.getByTestId('location-display')).toHaveTextContent(route)
143157
})
144158
```

0 commit comments

Comments
 (0)