mirror of
https://github.com/hanzoai/next.js.git
synced 2026-09-24 17:00:51 +00:00
### What? Refactors interception route regex generation to fix nested route navigation and improve maintainability. ### Why? Interception routes failed to trigger when navigating from nested descendant routes. The previous implementation had overly complex, fragile regex patterns spread across multiple functions that were difficult to maintain and didn't handle all navigation scenarios correctly. The root cause was an overly restrictive header matching pattern (`/[^/]+` - single segment only) that prevented matching navigation from deeper nested routes like `/groups/123/settings` → `/groups/123/new`. ### How? **Simplified Architecture:** - Consolidated regex generation logic into `route-regex.ts` where it properly belongs - Removed ~230 lines of complex, duplicated regex building code from `generate-interception-routes-rewrites.ts` - Leveraged existing `getNamedRouteRegex()` with a new `reference` parameter to handle parameter name mapping **Parameter Naming Fix:** - Introduced `nxtI` prefix for parameters adjacent to interception markers (e.g., `(.)[id]` → `nxtIid`) - Maintains `nxtP` prefix for regular parameters - Ensures consistent parameter naming across source, destination, and regex patterns **Regex Pattern Fix:** - Changed header matching from single-segment (`/[^/]+)?` to multi-segment `(/.+)?` pattern - Now correctly matches navigation from any descendant route depth **Test Coverage:** - Added comprehensive e2e tests for nested navigation scenarios - Updated existing tests to reflect new parameter naming convention Fixes #84813 NAR-445
69 lines
2.1 KiB
TypeScript
69 lines
2.1 KiB
TypeScript
import { nextTestSetup } from 'e2e-utils'
|
|
import { retry } from 'next-test-utils'
|
|
|
|
describe('interception-dynamic-segment-middleware', () => {
|
|
const { next } = nextTestSetup({
|
|
files: __dirname,
|
|
})
|
|
|
|
it('should work when interception route is paired with a dynamic segment & middleware', async () => {
|
|
const browser = await next.browser('/')
|
|
|
|
await browser.elementByCss('[href="/foo/p/1"]').click()
|
|
await retry(async () => {
|
|
expect(await browser.elementById('modal').text()).toMatch(/intercepted/)
|
|
})
|
|
await browser.refresh()
|
|
await retry(async () => {
|
|
expect(await browser.elementById('modal').text()).toBe('default')
|
|
})
|
|
await retry(async () => {
|
|
expect(await browser.elementById('children').text()).toMatch(
|
|
/not intercepted/
|
|
)
|
|
})
|
|
})
|
|
|
|
it('should intercept with back/forward navigation with middleware', async () => {
|
|
// Test that interception works correctly with middleware and browser navigation
|
|
const browser = await next.browser('/')
|
|
|
|
// Navigate with interception
|
|
await browser.elementByCss('[href="/foo/p/1"]').click()
|
|
await retry(async () => {
|
|
expect(await browser.elementById('modal').text()).toMatch(/intercepted/)
|
|
})
|
|
|
|
// Go back to root
|
|
await browser.back()
|
|
await retry(async () => {
|
|
const url = await browser.url()
|
|
expect(url).toContain('/')
|
|
})
|
|
|
|
// Go forward - should show intercepted version
|
|
await browser.forward()
|
|
await retry(async () => {
|
|
expect(await browser.elementById('modal').text()).toMatch(/intercepted/)
|
|
})
|
|
})
|
|
|
|
it('should intercept multiple times with middleware active', async () => {
|
|
// Test that repeated interception works when middleware is involved
|
|
const browser = await next.browser('/')
|
|
|
|
for (let i = 0; i < 2; i++) {
|
|
await browser.elementByCss('[href="/foo/p/1"]').click()
|
|
await retry(async () => {
|
|
expect(await browser.elementById('modal').text()).toMatch(/intercepted/)
|
|
})
|
|
|
|
await browser.back()
|
|
await retry(async () => {
|
|
const url = await browser.url()
|
|
expect(url).toMatch(/\/$/)
|
|
})
|
|
}
|
|
})
|
|
})
|