Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
226 changes: 126 additions & 100 deletions packages/react-router/tests/errorComponent.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
Link,
RouterProvider,
createBrowserHistory,
createLazyRoute,
createRootRoute,
createRoute,
createRouter,
Expand Down Expand Up @@ -38,110 +39,135 @@ afterEach(() => {
cleanup()
})

describe.each([{ preload: false }, { preload: 'intent' }] as const)(
'errorComponent is rendered when the preload=$preload',
(options) => {
describe.each([true, false])('with async=%s', (isAsync) => {
const throwableFn = isAsync ? asyncToThrowFn : throwFn

const callers = [
{ caller: 'beforeLoad', testFn: throwableFn },
{ caller: 'loader', testFn: throwableFn },
]

test.each(callers)(
'an Error is thrown on navigate in the route $caller function',
async ({ caller, testFn }) => {
const rootRoute = createRootRoute()
const indexRoute = createRoute({
getParentRoute: () => rootRoute,
path: '/',
component: function Home() {
return (
<div>
<Link to="/about">link to about</Link>
</div>
describe.each([true, false])(
'with lazy errorComponent=%s',
(isUsingLazyError) => {
describe.each([{ preload: false }, { preload: 'intent' }] as const)(
'errorComponent is rendered when the preload=$preload',
(options) => {
describe.each([true, false])('with async=%s', (isAsync) => {
const throwableFn = isAsync ? asyncToThrowFn : throwFn

const callers = [
{ caller: 'beforeLoad', testFn: throwableFn },
{ caller: 'loader', testFn: throwableFn },
]

test.each(callers)(
'an Error is thrown on navigate in the route $caller function',
async ({ caller, testFn }) => {
const rootRoute = createRootRoute()
const indexRoute = createRoute({
getParentRoute: () => rootRoute,
path: '/',
component: function Home() {
return (
<div>
<Link to="/about">link to about</Link>
</div>
)
},
})
const aboutRoute = createRoute({
getParentRoute: () => rootRoute,
path: '/about',
beforeLoad: caller === 'beforeLoad' ? testFn : undefined,
loader: caller === 'loader' ? testFn : undefined,
component: function Home() {
return <div>About route content</div>
},
errorComponent: isUsingLazyError ? undefined : MyErrorComponent,
})

if (isUsingLazyError) {
aboutRoute.lazy(() =>
Promise.resolve(
createLazyRoute('/about')({
errorComponent: MyErrorComponent,
}),
),
)
}

const routeTree = rootRoute.addChildren([indexRoute, aboutRoute])

const router = createRouter({
routeTree,
defaultPreload: options.preload,
history,
})

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

const linkToAbout = await screen.findByRole('link', {
name: 'link to about',
})

expect(linkToAbout).toBeInTheDocument()
fireEvent.mouseOver(linkToAbout)
fireEvent.focus(linkToAbout)
fireEvent.click(linkToAbout)

const errorComponent = await screen.findByText(
`Error: error thrown`,
undefined,
{ timeout: 1500 },
)
await expect(
screen.findByText('About route content'),
).rejects.toThrow()
expect(errorComponent).toBeInTheDocument()
},
})
const aboutRoute = createRoute({
getParentRoute: () => rootRoute,
path: '/about',
beforeLoad: caller === 'beforeLoad' ? testFn : undefined,
loader: caller === 'loader' ? testFn : undefined,
component: function Home() {
return <div>About route content</div>
},
errorComponent: MyErrorComponent,
})

const routeTree = rootRoute.addChildren([indexRoute, aboutRoute])

const router = createRouter({
routeTree,
defaultPreload: options.preload,
history,
})

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

const linkToAbout = await screen.findByRole('link', {
name: 'link to about',
})

expect(linkToAbout).toBeInTheDocument()
fireEvent.mouseOver(linkToAbout)
fireEvent.focus(linkToAbout)
fireEvent.click(linkToAbout)

const errorComponent = await screen.findByText(
`Error: error thrown`,
undefined,
{ timeout: 1500 },
)
await expect(
screen.findByText('About route content'),
).rejects.toThrow()
expect(errorComponent).toBeInTheDocument()
},
)

test.each(callers)(
'an Error is thrown on first load in the route $caller function',
async ({ caller, testFn }) => {
const rootRoute = createRootRoute()
const indexRoute = createRoute({
getParentRoute: () => rootRoute,
path: '/',
beforeLoad: caller === 'beforeLoad' ? testFn : undefined,
loader: caller === 'loader' ? testFn : undefined,
component: function Home() {
return <div>Index route content</div>
},
errorComponent: MyErrorComponent,
})

const routeTree = rootRoute.addChildren([indexRoute])

const router = createRouter({
routeTree,
defaultPreload: options.preload,
history,
})

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

const errorComponent = await screen.findByText(
`Error: error thrown`,
undefined,
{ timeout: 750 },
test.each(callers)(
'an Error is thrown on first load in the route $caller function',
async ({ caller, testFn }) => {
const rootRoute = createRootRoute()
const indexRoute = createRoute({
getParentRoute: () => rootRoute,
path: '/',
beforeLoad: caller === 'beforeLoad' ? testFn : undefined,
loader: caller === 'loader' ? testFn : undefined,
component: function Home() {
return <div>Index route content</div>
},
errorComponent: isUsingLazyError ? undefined : MyErrorComponent,
})

if (isUsingLazyError) {
indexRoute.lazy(() =>
Promise.resolve(
createLazyRoute('/')({
errorComponent: MyErrorComponent,
}),
),
)
}

const routeTree = rootRoute.addChildren([indexRoute])

const router = createRouter({
routeTree,
defaultPreload: options.preload,
history,
})

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

const errorComponent = await screen.findByText(
`Error: error thrown`,
undefined,
{ timeout: 750 },
)
await expect(
screen.findByText('Index route content'),
).rejects.toThrow()
expect(errorComponent).toBeInTheDocument()
},
)
await expect(
screen.findByText('Index route content'),
).rejects.toThrow()
expect(errorComponent).toBeInTheDocument()
},
)
})
})
},
)
},
)
Loading
Loading