mirror of
https://github.com/hanzoai/next.js.git
synced 2026-09-24 17:00:51 +00:00
### What When using `generateStaticParams` with interception routes, the interception would never occur, and instead an MPA navigation would take place to the targeted link. ### Why For interception rewrites, we use a `__NEXT_EMPTY_PARAM__` marker (in place of the actual param slot, eg `:locale`) for any params that are discovered prior to the interception marker. This is because during route resolution, the `params` for the interception route might not contain the same `params` for the page that triggered the interception. The dynamic params are then extracted from `FlightRouterState` at render time. However, when `generateStaticParams` is present, the `FlightRouterState` header is stripped from the request, so it isn't able to extract the dynamic params and so the router thinks the new tree is a new root layout, hence the MPA navigation. ### How This removes the `__NEXT_EMPTY_PARAM__` hack and several spots where we were forcing interception routes to be dynamic as a workaround to the above bug. Now when resolving the route, if the request was to an interception route, we extract the dynamic params from the request before constructing the final rewritten URL. This will ensure that the params from the "current" route are available in addition to the params from the interception route without needing to defer until render. Fixes #65192 Fixes #52880
73 lines
2.3 KiB
TypeScript
73 lines
2.3 KiB
TypeScript
import { nextTestSetup, FileRef } from 'e2e-utils'
|
|
import { retry } from 'next-test-utils'
|
|
import { join } from 'path'
|
|
|
|
describe('interception-route-prefetch-cache', () => {
|
|
function runTests({ next }: ReturnType<typeof nextTestSetup>) {
|
|
it('should render the correct interception when two distinct layouts share the same path structure', async () => {
|
|
const browser = await next.browser('/')
|
|
await browser.waitForIdleNetwork()
|
|
|
|
await browser.elementByCss('[href="/foo"]').click()
|
|
|
|
await retry(async () => {
|
|
expect(await browser.elementById('children').text()).toMatch(/Foo Page/)
|
|
})
|
|
|
|
await browser.elementByCss('[href="/post/1"]').click()
|
|
|
|
await retry(async () => {
|
|
// Ensure the existing page content is still the same
|
|
expect(await browser.elementById('children').text()).toMatch(/Foo Page/)
|
|
|
|
// Verify we got the right interception
|
|
expect(await browser.elementById('slot').text()).toMatch(
|
|
/Intercepted on Foo Page/
|
|
)
|
|
})
|
|
|
|
// Go back home. At this point, the router cache should have content from /foo
|
|
// Now we want to ensure that /bar doesn't share that same prefetch cache entry
|
|
await browser.elementByCss('[href="/"]').click()
|
|
|
|
await browser.waitForElementByCss('#home')
|
|
|
|
await browser.elementByCss('[href="/bar"]').click()
|
|
|
|
await retry(async () => {
|
|
expect(await browser.elementById('children').text()).toMatch(/Bar Page/)
|
|
})
|
|
|
|
await browser.elementByCss('[href="/post/1"]').click()
|
|
|
|
// Ensure the existing page content is still the same. If the prefetch cache resolved the wrong cache node
|
|
// then we'd see the content from /foo
|
|
await retry(async () => {
|
|
expect(await browser.elementById('children').text()).toMatch(/Bar Page/)
|
|
expect(await browser.elementById('slot').text()).toMatch(
|
|
/Intercepted on Bar Page/
|
|
)
|
|
})
|
|
})
|
|
}
|
|
|
|
describe('runtime = nodejs', () => {
|
|
runTests(
|
|
nextTestSetup({
|
|
files: __dirname,
|
|
})
|
|
)
|
|
})
|
|
|
|
describe('runtime = edge', () => {
|
|
runTests(
|
|
nextTestSetup({
|
|
files: {
|
|
app: new FileRef(join(__dirname, 'app')),
|
|
'app/layout.tsx': new FileRef(join(__dirname, 'app/layout-edge.tsx')),
|
|
},
|
|
})
|
|
)
|
|
})
|
|
})
|