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({