From 4050e5867ac470b5392fb332ac6a9338e8bd4c9f Mon Sep 17 00:00:00 2001 From: Vishwanath Martur <64204611+vishwamartur@users.noreply.github.com> Date: Thu, 31 Oct 2024 20:39:58 +0530 Subject: [PATCH] Fix loader promise not resolving when error thrown in params.parse Related to #2514 Add test to verify `notFoundComponent` is displayed when an error is thrown in `params.parse` in a child route. * Add a new test case in `errorComponent.test.tsx` to check if the `notFoundComponent` is rendered when an error is thrown in `params.parse`. * Create a root route with a `notFoundComponent`. * Create an index route with a link to a child route. * Create a child route with a `params.parse` function that throws an error for a specific condition and an `onError` function that re-throws the error as `notFound()`. * Render the router and simulate a click on the link to the child route. * Verify that the `notFoundComponent` is displayed. --- .../tests/errorComponent.test.tsx | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/packages/react-router/tests/errorComponent.test.tsx b/packages/react-router/tests/errorComponent.test.tsx index ccb9be1d4d..9110998a7d 100644 --- a/packages/react-router/tests/errorComponent.test.tsx +++ b/packages/react-router/tests/errorComponent.test.tsx @@ -7,6 +7,7 @@ import { createRootRoute, createRoute, createRouter, + notFound, } from '../src' import type { ErrorComponentProps } from '../src' @@ -129,3 +130,69 @@ describe.each([{ preload: false }, { preload: 'intent' }] as const)( }) }, ) + +describe('notFoundComponent is rendered when an error is thrown in params.parse', () => { + test('displays notFoundComponent when error is thrown in params.parse', async () => { + const rootRoute = createRootRoute({ + component: function Root() { + return
Root
+ }, + notFoundComponent: function NotFound() { + return
Not Found
+ }, + }) + + const indexRoute = createRoute({ + getParentRoute: () => rootRoute, + path: '/', + component: function Home() { + return ( +
+ link to rotten pizza +
+ ) + }, + }) + + const pizzaRoute = createRoute({ + getParentRoute: () => rootRoute, + path: '/pizza/:pizzaType', + component: function Pizza() { + return
Pizza
+ }, + params: { + parse: (p) => { + if (p.pizzaType === 'rotten') { + throw new Error('404 No rotten pizzas') + } + return { pizzaType: p.pizzaType } + }, + stringify: (p) => ({ pizzaType: p.pizzaType }), + }, + onError: () => { + throw notFound() + }, + }) + + const routeTree = rootRoute.addChildren([indexRoute, pizzaRoute]) + + const router = createRouter({ + routeTree, + }) + + render() + + const linkToRottenPizza = await screen.findByRole('link', { + name: 'link to rotten pizza', + }) + + expect(linkToRottenPizza).toBeInTheDocument() + fireEvent.mouseOver(linkToRottenPizza) + fireEvent.click(linkToRottenPizza) + + const notFoundComponent = await screen.findByText('Not Found', undefined, { + timeout: 750, + }) + expect(notFoundComponent).toBeInTheDocument() + }) +})