Skip to content

Commit

Permalink
test(react-router): check the availability of the route context after…
Browse files Browse the repository at this point in the history
… a redirect on the first load (#1710)

* test(react-router): check in component-land about redirects

* test(react-router): do the same for the beforeLoad and loader spots

* chore: whoops

* test: make sure the pathnames are checked
  • Loading branch information
SeanCassiere authored Jun 5, 2024
1 parent 07a6fde commit 9bb0148
Showing 1 changed file with 184 additions and 0 deletions.
184 changes: 184 additions & 0 deletions packages/react-router/tests/routeContext.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
RouterProvider,
useRouteContext,
rootRouteId,
redirect,
} from '../src'

import { sleep } from './utils'
Expand Down Expand Up @@ -133,6 +134,67 @@ describe('beforeLoad in the route definition', () => {
expect(mock).toHaveBeenCalledWith({ foo: 'sean' })
expect(mock).toHaveBeenCalledTimes(1)
})

// Check if context the context is available after a redirect
test('route context is present in the /about route after a redirect is thrown in the beforeLoad of the index route', async () => {
const mock = vi.fn()

const rootRoute = createRootRoute()
const indexRoute = createRoute({
getParentRoute: () => rootRoute,
path: '/',
beforeLoad: async () => {
await sleep(WAIT_TIME)
throw redirect({ to: '/about' })
},
})
const aboutRoute = createRoute({
getParentRoute: () => rootRoute,
path: '/about',
beforeLoad: async ({ context }) => {
mock(context)
},
})
const routeTree = rootRoute.addChildren([aboutRoute, indexRoute])
const router = createRouter({ routeTree, context: { foo: 'bar' } })

render(<RouterProvider router={router} />)

await waitFor(() => expect(mock).toHaveBeenCalledOnce())
expect(mock).toHaveBeenCalledWith({ foo: 'bar' })
expect(mock).toHaveBeenCalledTimes(1)
expect(router.state.location.pathname).toBe('/about')
})

test('route context is present in the /about route after a redirect is thrown in the loader of the index route', async () => {
const mock = vi.fn()

const rootRoute = createRootRoute()
const indexRoute = createRoute({
getParentRoute: () => rootRoute,
path: '/',
loader: async () => {
await sleep(WAIT_TIME)
throw redirect({ to: '/about' })
},
})
const aboutRoute = createRoute({
getParentRoute: () => rootRoute,
path: '/about',
beforeLoad: async ({ context }) => {
mock(context)
},
})
const routeTree = rootRoute.addChildren([aboutRoute, indexRoute])
const router = createRouter({ routeTree, context: { foo: 'bar' } })

render(<RouterProvider router={router} />)

await waitFor(() => expect(mock).toHaveBeenCalledOnce())
expect(mock).toHaveBeenCalledWith({ foo: 'bar' })
expect(mock).toHaveBeenCalledTimes(1)
expect(router.state.location.pathname).toBe('/about')
})
})

describe('loader in the route definition', () => {
Expand Down Expand Up @@ -247,6 +309,67 @@ describe('loader in the route definition', () => {
expect(mock).toHaveBeenCalledWith({ foo: 'sean' })
expect(mock).toHaveBeenCalledTimes(1)
})

// Check if context the context is available after a redirect
test('route context is present in the /about route after a redirect is thrown in beforeLoad of the index route', async () => {
const mock = vi.fn()

const rootRoute = createRootRoute()
const indexRoute = createRoute({
getParentRoute: () => rootRoute,
path: '/',
beforeLoad: async () => {
await sleep(WAIT_TIME)
throw redirect({ to: '/about' })
},
})
const aboutRoute = createRoute({
getParentRoute: () => rootRoute,
path: '/about',
loader: async ({ context }) => {
mock(context)
},
})
const routeTree = rootRoute.addChildren([aboutRoute, indexRoute])
const router = createRouter({ routeTree, context: { foo: 'bar' } })

render(<RouterProvider router={router} />)

await waitFor(() => expect(mock).toHaveBeenCalledOnce())
expect(mock).toHaveBeenCalledWith({ foo: 'bar' })
expect(mock).toHaveBeenCalledTimes(1)
expect(router.state.location.pathname).toBe('/about')
})

test('route context is present in the /about route after a redirect is thrown in loader of the index route', async () => {
const mock = vi.fn()

const rootRoute = createRootRoute()
const indexRoute = createRoute({
getParentRoute: () => rootRoute,
path: '/',
loader: async () => {
await sleep(WAIT_TIME)
throw redirect({ to: '/about' })
},
})
const aboutRoute = createRoute({
getParentRoute: () => rootRoute,
path: '/about',
loader: async ({ context }) => {
mock(context)
},
})
const routeTree = rootRoute.addChildren([aboutRoute, indexRoute])
const router = createRouter({ routeTree, context: { foo: 'bar' } })

render(<RouterProvider router={router} />)

await waitFor(() => expect(mock).toHaveBeenCalledOnce())
expect(mock).toHaveBeenCalledWith({ foo: 'bar' })
expect(mock).toHaveBeenCalledTimes(1)
expect(router.state.location.pathname).toBe('/about')
})
})

describe('useRouteContext in the component', () => {
Expand Down Expand Up @@ -435,4 +558,65 @@ describe('useRouteContext in the component', () => {

expect(content).toBeInTheDocument()
})

// Check if context the context is available after a redirect
test('route context is present in the /about route after a redirect is thrown in the beforeLoad of the index route', async () => {
const rootRoute = createRootRoute()
const indexRoute = createRoute({
getParentRoute: () => rootRoute,
path: '/',
beforeLoad: async () => {
await sleep(WAIT_TIME)
throw redirect({ to: '/about' })
},
})
const aboutRoute = createRoute({
getParentRoute: () => rootRoute,
path: '/about',
component: () => {
const context = useRouteContext({ from: rootRouteId })
return <div>{JSON.stringify(context)}</div>
},
})
const routeTree = rootRoute.addChildren([aboutRoute, indexRoute])
const router = createRouter({ routeTree, context: { foo: 'bar' } })

render(<RouterProvider router={router} />)

const content = await screen.findByText(JSON.stringify({ foo: 'bar' }))

expect(router.state.location.href).toBe('/about')
expect(window.location.pathname).toBe('/about')
expect(content).toBeInTheDocument()
})

test('route context is present in the /about route after a redirect is thrown in the loader of the index route', async () => {
const rootRoute = createRootRoute()
const indexRoute = createRoute({
getParentRoute: () => rootRoute,
path: '/',
loader: async () => {
await sleep(WAIT_TIME)
throw redirect({ to: '/about' })
},
})
const aboutRoute = createRoute({
getParentRoute: () => rootRoute,
path: '/about',
component: () => {
const context = useRouteContext({ from: rootRouteId })
return <div>{JSON.stringify(context)}</div>
},
})
const routeTree = rootRoute.addChildren([aboutRoute, indexRoute])
const router = createRouter({ routeTree, context: { foo: 'bar' } })

render(<RouterProvider router={router} />)

const content = await screen.findByText(JSON.stringify({ foo: 'bar' }))

expect(router.state.location.href).toBe('/about')
expect(window.location.pathname).toBe('/about')
expect(content).toBeInTheDocument()
})
})

0 comments on commit 9bb0148

Please sign in to comment.