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
12 changes: 8 additions & 4 deletions packages/router-core/src/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1379,7 +1379,7 @@ export class RouterCore<

const strictParams = existingMatch?._strictParams ?? usedParams

let paramsError: PathParamError | undefined = undefined
let paramsError: unknown = undefined

if (!existingMatch) {
const strictParseParams =
Expand All @@ -1392,9 +1392,13 @@ export class RouterCore<
strictParseParams(strictParams as Record<string, string>),
)
} catch (err: any) {
paramsError = new PathParamError(err.message, {
cause: err,
})
if (isNotFound(err) || isRedirect(err)) {
paramsError = err
} else {
paramsError = new PathParamError(err.message, {
cause: err,
})
}

if (opts?.throwOnError) {
throw paramsError
Expand Down
60 changes: 60 additions & 0 deletions packages/router-core/tests/load.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,66 @@ test('cancelMatches after pending timeout', async () => {
expect(cancelledFooMatch?._nonReactive.pendingTimeout).toBeUndefined()
})

describe('params.parse notFound', () => {
test('throws notFound on invalid params', async () => {
const rootRoute = new BaseRootRoute({})
const testRoute = new BaseRoute({
getParentRoute: () => rootRoute,
path: '/test/$id',
params: {
parse: ({ id }: { id: string }) => {
const parsed = parseInt(id, 10)
if (Number.isNaN(parsed)) {
throw notFound()
}
return { id: parsed }
},
},
})
const routeTree = rootRoute.addChildren([testRoute])
const router = new RouterCore({
routeTree,
history: createMemoryHistory({ initialEntries: ['/test/invalid'] }),
})

await router.load()

const match = router.state.pendingMatches?.find(
(m) => m.routeId === testRoute.id,
)

expect(match?.status).toBe('notFound')
})
Comment on lines +513 to +541
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add statusCode assertion to verify 404 response.

The test verifies the match status is 'notFound' but doesn't check that the router's statusCode is set to 404. According to the PR objectives, this test should verify both the match status and the statusCode.

Add this assertion after line 540:

 expect(match?.status).toBe('notFound')
+expect(router.state.statusCode).toBe(404)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
test('throws notFound on invalid params', async () => {
const rootRoute = new BaseRootRoute({})
const testRoute = new BaseRoute({
getParentRoute: () => rootRoute,
path: '/test/$id',
params: {
parse: ({ id }: { id: string }) => {
const parsed = parseInt(id, 10)
if (Number.isNaN(parsed)) {
throw notFound()
}
return { id: parsed }
},
},
})
const routeTree = rootRoute.addChildren([testRoute])
const router = new RouterCore({
routeTree,
history: createMemoryHistory({ initialEntries: ['/test/invalid'] }),
})
await router.load()
const match = router.state.pendingMatches?.find(
(m) => m.routeId === testRoute.id,
)
expect(match?.status).toBe('notFound')
})
test('throws notFound on invalid params', async () => {
const rootRoute = new BaseRootRoute({})
const testRoute = new BaseRoute({
getParentRoute: () => rootRoute,
path: '/test/$id',
params: {
parse: ({ id }: { id: string }) => {
const parsed = parseInt(id, 10)
if (Number.isNaN(parsed)) {
throw notFound()
}
return { id: parsed }
},
},
})
const routeTree = rootRoute.addChildren([testRoute])
const router = new RouterCore({
routeTree,
history: createMemoryHistory({ initialEntries: ['/test/invalid'] }),
})
await router.load()
const match = router.state.pendingMatches?.find(
(m) => m.routeId === testRoute.id,
)
expect(match?.status).toBe('notFound')
expect(router.state.statusCode).toBe(404)
})
🤖 Prompt for AI Agents
In packages/router-core/tests/load.test.ts around lines 513 to 541, the test
checks that the match status is 'notFound' but doesn't assert the router's
overall statusCode; add an assertion after the existing
expect(match?.status).toBe('notFound') to also expect router.statusCode to equal
404 so the test verifies both the match status and the router's 404 statusCode.


test('succeeds on valid params', async () => {
const rootRoute = new BaseRootRoute({})
const testRoute = new BaseRoute({
getParentRoute: () => rootRoute,
path: '/test/$id',
params: {
parse: ({ id }: { id: string }) => {
const parsed = parseInt(id, 10)
if (Number.isNaN(parsed)) {
throw notFound()
}
return { id: parsed }
},
},
})
const routeTree = rootRoute.addChildren([testRoute])
const router = new RouterCore({
routeTree,
history: createMemoryHistory({ initialEntries: ['/test/123'] }),
})

await router.load()

const match = router.state.matches.find((m) => m.routeId === testRoute.id)
expect(match?.status).toBe('success')
expect(router.state.statusCode).toBe(200)
})
})

function sleep(ms: number) {
return new Promise<void>((resolve) => setTimeout(resolve, ms))
}
Loading