rsnext/test/e2e/app-dir/parallel-routes-catchall/parallel-routes-catchall.test.ts
Zack Tanner 31a0edbd1b
parallel routes: fix catch-all slots being treated as optional catch-all (#61174)
### What
Catch-all parallel slots were being incorrectly matched to the root of their segment. For example, `@foo/[...catchAll]/page` as a parallel route on `/page.tsx` should not match on `/`, but it should match on `/foo`, `/bar`, ...etc

### Why
The catch-all route normalization logic doesn't treat optional catch-all routes differently from catch-all routes. The assumption was if any catch-all route was found, that it should match the path that shared its prefix.

### How
This updates the normalization logic to handle optional-catchall as it was in the original implementation. For regular catch-all, we ensure that the catch-all base path (for `/[...slug]` that'd be `/`) isn't identical to the path we'd match it to.

Fixes #60613
Closes NEXT-2243
2024-01-30 15:28:47 -08:00

65 lines
2.6 KiB
TypeScript

import { createNextDescribe } from 'e2e-utils'
import { check } from 'next-test-utils'
createNextDescribe(
'parallel-routes-catchall',
{
files: __dirname,
},
({ next }) => {
it('should match correctly when defining an explicit page & slot', async () => {
const browser = await next.browser('/')
await check(() => browser.elementById('slot').text(), /@slot default/)
await browser.elementByCss('[href="/foo"]').click()
// foo has defined a page route and a corresponding parallel slot
// so we'd expect to see the custom slot content & the page content
await check(() => browser.elementById('children').text(), /foo/)
await check(() => browser.elementById('slot').text(), /foo slot/)
})
it('should match correctly when defining an explicit page but no slot', async () => {
const browser = await next.browser('/')
await check(() => browser.elementById('slot').text(), /@slot default/)
await browser.elementByCss('[href="/bar"]').click()
// bar has defined a slot but no page route
// so we'd expect to see the catch-all slot & the page content
await check(() => browser.elementById('children').text(), /bar/)
await check(() => browser.elementById('slot').text(), /slot catchall/)
await check(
() => browser.elementById('slot').text(),
/catchall slot client component/
)
})
it('should match correctly when defining an explicit slot but no page', async () => {
const browser = await next.browser('/')
await check(() => browser.elementById('slot').text(), /@slot default/)
await browser.elementByCss('[href="/baz"]').click()
// baz has defined a page route and a corresponding parallel slot
// so we'd expect to see the custom slot content & the page content
await check(() => browser.elementById('children').text(), /main catchall/)
await check(() => browser.elementById('slot').text(), /baz slot/)
})
it('should match both the catch-all page & slot', async () => {
const browser = await next.browser('/')
await check(() => browser.elementById('slot').text(), /@slot default/)
await browser.elementByCss('[href="/quux"]').click()
// quux doesn't have a page or slot defined. It should use the catch-all for both
await check(() => browser.elementById('children').text(), /main catchall/)
await check(() => browser.elementById('slot').text(), /slot catchall/)
await check(
() => browser.elementById('slot').text(),
/catchall slot client component/
)
})
}
)