-
Notifications
You must be signed in to change notification settings - Fork 26.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix intercepting route behavior in route groups
- Loading branch information
Showing
14 changed files
with
263 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
5 changes: 5 additions & 0 deletions
5
.../interception-route-groups/app/(level1)/(level2)/(level3)/@slot/(...)photos/[id]/page.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import React from 'react' | ||
|
||
export default function Page({ params }: { params: { id: string } }) { | ||
return <div>Intercepted Photo Page {params.id}</div> | ||
} |
3 changes: 3 additions & 0 deletions
3
test/e2e/app-dir/interception-route-groups/app/(level1)/(level2)/(level3)/@slot/default.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export default function Default() { | ||
return <div>@slot default</div> | ||
} |
11 changes: 11 additions & 0 deletions
11
test/e2e/app-dir/interception-route-groups/app/(level1)/(level2)/(level3)/layout.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
export default function Layout(props: { | ||
children: React.ReactNode | ||
slot: React.ReactNode | ||
}) { | ||
return ( | ||
<div> | ||
<div id="children">{props.children}</div> | ||
<div id="slot">{props.slot}</div> | ||
</div> | ||
) | ||
} |
9 changes: 9 additions & 0 deletions
9
...e2e/app-dir/interception-route-groups/app/(level1)/(level2)/(level3)/photos/[id]/page.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import Link from 'next/link' | ||
|
||
export default function Page({ params }: { params: { id: string } }) { | ||
return ( | ||
<div> | ||
Photo Page (non-intercepted) {params.id} <Link href="/">Back Home</Link> | ||
</div> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
export default function Layout(props: { children: React.ReactNode }) { | ||
return ( | ||
<html> | ||
<body> | ||
<div id="children">{props.children}</div> | ||
</body> | ||
</html> | ||
) | ||
} |
5 changes: 5 additions & 0 deletions
5
...terception-route-groups/app/nested/(level1)/(level2)/@intercepted/(.)photos/[id]/page.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import React from 'react' | ||
|
||
export default function Page({ params }: { params: { id: string } }) { | ||
return <div>Intercepted Photo Page {params.id}</div> | ||
} |
3 changes: 3 additions & 0 deletions
3
...e/app-dir/interception-route-groups/app/nested/(level1)/(level2)/@intercepted/default.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export default function Page() { | ||
return <div>@intercepted default</div> | ||
} |
11 changes: 11 additions & 0 deletions
11
test/e2e/app-dir/interception-route-groups/app/nested/(level1)/(level2)/layout.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
export default function Layout(props: { | ||
children: React.ReactNode | ||
intercepted: React.ReactNode | ||
}) { | ||
return ( | ||
<div> | ||
<div id="children">{props.children}</div> | ||
<div id="slot">{props.intercepted}</div> | ||
</div> | ||
) | ||
} |
10 changes: 10 additions & 0 deletions
10
test/e2e/app-dir/interception-route-groups/app/nested/(level1)/(level2)/photos/[id]/page.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import Link from 'next/link' | ||
|
||
export default function Page({ params }: { params: { id: string } }) { | ||
return ( | ||
<div> | ||
Photo Page (non-intercepted) {params.id}{' '} | ||
<Link href="/nested">Back to /nested</Link> | ||
</div> | ||
) | ||
} |
3 changes: 3 additions & 0 deletions
3
test/e2e/app-dir/interception-route-groups/app/nested/default.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export default function Default() { | ||
return <div>Default Children (nested)</div> | ||
} |
10 changes: 10 additions & 0 deletions
10
test/e2e/app-dir/interception-route-groups/app/nested/page.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import Link from 'next/link' | ||
|
||
export default function Page() { | ||
return ( | ||
<div> | ||
<Link href="/nested/photos/1">Photo 1</Link>{' '} | ||
<Link href="/nested/photos/2">Photo 2</Link> | ||
</div> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import Link from 'next/link' | ||
|
||
export default function Page() { | ||
return ( | ||
<div> | ||
<Link href="/photos/1">Photo 1</Link>{' '} | ||
<Link href="/photos/2">Photo 2</Link> | ||
<hr /> | ||
<Link href="/nested">To /nested</Link> | ||
</div> | ||
) | ||
} |
153 changes: 153 additions & 0 deletions
153
test/e2e/app-dir/interception-route-groups/interception-route-groups.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,153 @@ | ||
import { createNextDescribe } from 'e2e-utils' | ||
import { check } from 'next-test-utils' | ||
import { FileRef } from 'e2e-utils' | ||
import path from 'path' | ||
|
||
createNextDescribe( | ||
'interception route groups (with default)', | ||
{ | ||
files: { | ||
app: new FileRef(path.join(__dirname, 'app')), | ||
'app/default.tsx': ` | ||
export default function Default() { | ||
return <div>Default Children (Root)</div> | ||
} | ||
`, | ||
}, | ||
}, | ||
({ next }) => { | ||
it("should render the root default when a route group doesn't have a default", async () => { | ||
const browser = await next.browser('/') | ||
|
||
await browser.elementByCss('[href="/photos/1"]').click() | ||
// this route was intercepted, so we should see the slot contain the page content | ||
await check( | ||
() => browser.elementById('slot').text(), | ||
/Intercepted Photo Page 1/ | ||
) | ||
|
||
// and the children slot should be whatever is specified by default (in this case, default is defined at the root of the app) | ||
await check( | ||
() => browser.elementById('children').text(), | ||
/Default Children \(Root\)/ | ||
) | ||
|
||
await browser.refresh() | ||
|
||
// once we reload, the route is no longer intercepted. The slot will fallback to the default | ||
// and the children slot will be whatever is specified by the corresponding page component | ||
await check(() => browser.elementById('slot').text(), /@slot default/) | ||
await check( | ||
() => browser.elementById('children').text(), | ||
/Photo Page \(non-intercepted\) 1/ | ||
) | ||
|
||
await browser.elementByCss('[href="/"]').click() | ||
|
||
// perform the same checks as above, but with the other page | ||
await browser.elementByCss('[href="/photos/2"]').click() | ||
await check( | ||
() => browser.elementById('slot').text(), | ||
/Intercepted Photo Page 2/ | ||
) | ||
await check( | ||
() => browser.elementById('children').text(), | ||
/Default Children \(Root\)/ | ||
) | ||
|
||
await browser.refresh() | ||
|
||
await check(() => browser.elementById('slot').text(), /@slot default/) | ||
await check( | ||
() => browser.elementById('children').text(), | ||
/Photo Page \(non-intercepted\) 2/ | ||
) | ||
}) | ||
|
||
it('should work when nested a level deeper', async () => { | ||
const browser = await next.browser('/nested') | ||
await browser.elementByCss('[href="/nested/photos/1"]').click() | ||
|
||
// this route was intercepted, so we should see the slot contain the page content | ||
await check( | ||
() => browser.elementById('slot').text(), | ||
/Intercepted Photo Page 1/ | ||
) | ||
|
||
// and the children slot should be whatever is specified by default (in this case, default is defined at `/nested/default`) | ||
await check( | ||
() => browser.elementById('children').text(), | ||
/Default Children \(nested\)/ | ||
) | ||
|
||
await browser.refresh() | ||
|
||
// once we reload, the route is no longer intercepted. The slot will fallback to the default | ||
// and the children slot will be whatever is specified by the corresponding page component | ||
await check( | ||
() => browser.elementById('slot').text(), | ||
/@intercepted default/ | ||
) | ||
await check( | ||
() => browser.elementById('children').text(), | ||
/Photo Page \(non-intercepted\) 1/ | ||
) | ||
|
||
await browser.elementByCss('[href="/nested"]').click() | ||
|
||
// perform the same checks as above, but with the other page | ||
await browser.elementByCss('[href="/nested/photos/2"]').click() | ||
await check( | ||
() => browser.elementById('slot').text(), | ||
/Intercepted Photo Page 2/ | ||
) | ||
await check( | ||
() => browser.elementById('children').text(), | ||
/Default Children \(nested\)/ | ||
) | ||
|
||
await browser.refresh() | ||
|
||
await check( | ||
() => browser.elementById('slot').text(), | ||
/@intercepted default/ | ||
) | ||
await check( | ||
() => browser.elementById('children').text(), | ||
/Photo Page \(non-intercepted\) 2/ | ||
) | ||
}) | ||
} | ||
) | ||
|
||
createNextDescribe( | ||
'interception route groups (no default)', | ||
{ | ||
files: { | ||
app: new FileRef(path.join(__dirname, 'app')), | ||
}, | ||
}, | ||
({ next, isNextStart }) => { | ||
if (process.env.__NEXT_EXPERIMENTAL_PPR === 'true' && isNextStart) { | ||
// The PPR prefetch will 404 since it'll request the full page (which won't exist, since the intercepted route | ||
// has no default). The default router behavior if a prefetch fails is to trigger an MPA navigation | ||
it('should render the non-intercepted page on navigation', async () => { | ||
const browser = await next.browser('/') | ||
|
||
await browser.elementByCss('[href="/photos/1"]').click() | ||
await check(() => browser.elementById('slot').text(), '') | ||
await check( | ||
() => browser.elementById('children').text(), | ||
/Photo Page \(non-intercepted\) 1/ | ||
) | ||
}) | ||
} else { | ||
it('should use the default fallback (a 404) if there is no custom default page', async () => { | ||
const browser = await next.browser('/') | ||
|
||
await browser.elementByCss('[href="/photos/1"]').click() | ||
await check(() => browser.elementByCss('body').text(), /404/) | ||
}) | ||
} | ||
} | ||
) |