From 4213d97283c7c05b5135a07e3929924841d27183 Mon Sep 17 00:00:00 2001 From: Raghuram Bharathan <rram@rocketmail.com> Date: Fri, 23 Jun 2023 14:53:24 +0530 Subject: [PATCH] Fixes #1265 Updated example for react-router v6.4 --- docs/example-react-router.mdx | 154 +++++++++++++++++++++++++++++++++- 1 file changed, 153 insertions(+), 1 deletion(-) diff --git a/docs/example-react-router.mdx b/docs/example-react-router.mdx index 530bb5f3b..776675787 100644 --- a/docs/example-react-router.mdx +++ b/docs/example-react-router.mdx @@ -3,7 +3,159 @@ id: example-react-router title: React Router --- -This example demonstrates React Router v6. For previous versions see below. +This example demonstrates React Router v6.4 and above. For previous versions see below. + +```jsx +// App.jsx +import { + createBrowserRouter, + Form, + Link, + Outlet, + redirect, + RouterProvider, + useLoaderData, + useLocation, +} from 'react-router-dom'; + +// Method to introduce an artificial delay +export function sleep(n = 500) { + return new Promise((r) => setTimeout(r, n)); +} + +// Loader to return after a small delay +export async function homeLoader() { + await sleep(); + return { + message: 'home', + }; +} + +// Action to get user input +export async function aboutAction({ request }) { + await sleep(); + let formData = await request.formData(); + let name = formData.get('name'); + console.log(name); + // Call an async method to add and so on + return redirect('/'); +} + +export const About = () => { + return ( + <> + <div>You are on the about page</div> + <Form method="post"> + <input name="person" placeholder="Name" /> + <button type="submit">Submit</button> + </Form> + </> + ); +}; + +export const Home = () => { + let data = useLoaderData(); + return <div>You are {data.message}</div>; +}; + +export const NoMatch = () => <div>No match</div>; + +export const LocationDisplay = () => { + const location = useLocation(); + + return <div data-testid="location-display">{location.pathname}</div>; +}; + +export const Layout = () => ( + <div> + <Link to="/">Home</Link> + <Link to="/about">About</Link> + <Outlet /> + <LocationDisplay /> + </div> +); + +export const routes = [ + { + path: '/', + element: <Layout />, + children: [ + { + index: true, + element: <Home />, + loader: homeLoader, + }, + { + path: '/about', + element: <About />, + action: aboutAction, + }, + { + path: '*', + element: <NoMatch />, + }, + ], + }, +]; + +const router = createBrowserRouter(routes); + +const App = () => <RouterProvider router={router}></RouterProvider>; + +export default App; +``` + +```jsx +// App.test.jsx +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import React from 'react'; +import '@testing-library/jest-dom'; +import { + createBrowserRouter, + createMemoryRouter, + RouterProvider, +} from 'react-router-dom'; +import { routes } from './App'; + +test('full app rendering/navigating', async () => { + const router = createBrowserRouter(routes); + render(<RouterProvider router={router}></RouterProvider>); + + const user = userEvent.setup(); + // We need to wait for the loader data and then assert presence + expect(await screen.findByText(/you are home/i)).toBeInTheDocument(); + + // verify page content for expected route after navigating + await user.click(screen.getByText(/about/i)); + expect(screen.getByText(/you are on the about page/i)).toBeInTheDocument(); +}); + +test('landing on a bad page', () => { + const badRoute = '/some/bad/route'; + const router = createMemoryRouter(routes, { initialEntries: [badRoute] }); + + // use createMemoryRouter when you want to manually control the history + render(<RouterProvider router={router}></RouterProvider>); + + // verify navigation to "no match" route + expect(screen.getByText(/no match/i)).toBeInTheDocument(); +}); + +test('rendering a component that uses useLocation', () => { + const route = '/some-route'; + const router = createMemoryRouter(routes, { initialEntries: [route] }); + + // use createMemoryRouter when you want to manually control the history + render(<RouterProvider router={router}></RouterProvider>); + + // verify location display is rendered + expect(screen.getByTestId('location-display')).toHaveTextContent(route); +}); +``` +Refer to [this working example](https://stackblitz.com/edit/vitejs-vite-dnutcg?file=src%2FApp.test.jsx,src%2FApp.jsx) + +## Testing Library and React Router v6 ```jsx // app.js