31a0edbd1b
### 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
65 lines
2.6 KiB
TypeScript
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/
|
|
)
|
|
})
|
|
}
|
|
)
|