diff --git a/packages/react-router/tests/link.test.tsx b/packages/react-router/tests/link.test.tsx index b9c739becd..f06a3a8dec 100644 --- a/packages/react-router/tests/link.test.tsx +++ b/packages/react-router/tests/link.test.tsx @@ -27,6 +27,7 @@ import { createRouteMask, createRouter, getRouteApi, + notFound, redirect, retainSearchParams, stripSearchParams, @@ -1987,6 +1988,115 @@ describe('Link', () => { expect(notFoundComponent).not.toBeCalled() }) + test('404 thrown in child will bubble up to the root with beforeLoad', async () => { + const rootRoute = createRootRoute({ + notFoundComponent: () =>
Root notFoundComponent
, + beforeLoad: () => ({ ok: true }), + }) + const indexRoute = createRoute({ + getParentRoute: () => rootRoute, + path: '/', + component: () => { + return ( + <> +

Index

+ Non existing post + + ) + }, + }) + + const postRoute = createRoute({ + getParentRoute: () => rootRoute, + path: '$postId', + params: { + parse: (p) => { + if (p.postId === 'nonExistingPost') { + throw new Error('Post not exists') + } + return { + postId: p.postId, + } + }, + stringify: (p) => ({ postId: p.postId }), + }, + onError: () => { + throw notFound() + }, + component: () =>
Existing Post
, + }) + + const router = createRouter({ + routeTree: rootRoute.addChildren([indexRoute, postRoute]), + }) + + render() + + const postsLink = await screen.findByRole('link', { + name: 'Non existing post', + }) + await act(() => fireEvent.click(postsLink)) + + const errorText = await screen.findByText('Root notFoundComponent') + expect(errorText).toBeInTheDocument() + }) + + test('404 thrown in child will bubble up to the root with async loader', async () => { + const rootRoute = createRootRoute({ + notFoundComponent: () =>
Root notFoundComponent
, + loader: async () => { + await sleep(0) + return { ok: true } + }, + }) + const indexRoute = createRoute({ + getParentRoute: () => rootRoute, + path: '/', + component: () => { + return ( + <> +

Index

+ Non existing post + + ) + }, + }) + + const postRoute = createRoute({ + getParentRoute: () => rootRoute, + path: '$postId', + params: { + parse: (p) => { + if (p.postId === 'nonExistingPost') { + throw new Error('Post not exists') + } + return { + postId: p.postId, + } + }, + stringify: (p) => ({ postId: p.postId }), + }, + onError: () => { + throw notFound() + }, + component: () =>
Existing Post
, + }) + + const router = createRouter({ + routeTree: rootRoute.addChildren([indexRoute, postRoute]), + }) + + render() + + const postsLink = await screen.findByRole('link', { + name: 'Non existing post', + }) + await act(() => fireEvent.click(postsLink)) + + const errorText = await screen.findByText('Root notFoundComponent') + expect(errorText).toBeInTheDocument() + }) + test('when navigating to /posts with params', async () => { const rootRoute = createRootRoute() const indexRoute = createRoute({