11import { nextTestSetup } from 'e2e-utils'
22import { retry } from 'next-test-utils'
3+ import { Playwright } from 'next-webdriver'
34import { createRouterAct } from 'router-act'
45
56describe ( 'interception-dynamic-segment' , ( ) => {
67 const { next, isNextStart, isNextDev } = nextTestSetup ( {
78 files : __dirname ,
89 } )
910
11+ /**
12+ * Returns true if the given href should already be opened. This allows us to
13+ * condition on whether to expect any additional network requests.
14+ */
15+ async function isAccordionClosed (
16+ browser : Playwright ,
17+ href : string
18+ ) : Promise < boolean > {
19+ const selector = `[data-testid="link-accordion"][data-href="${ href } "]`
20+
21+ // Check if the button is already open
22+ return await browser . hasElementByCss ( `${ selector } button` )
23+ }
24+
25+ /**
26+ * Helper to navigate via the LinkAccordion component.
27+ * Scrolls to the accordion, opens it, and clicks the link.
28+ */
29+ async function navigate ( browser : Playwright , href : string ) {
30+ const selector = `[data-testid="link-accordion"][data-href="${ href } "]`
31+
32+ // Find and scroll to accordion
33+ const accordion = await browser . elementByCss ( selector )
34+ await accordion . scrollIntoViewIfNeeded ( )
35+
36+ // Click the "Open" button, it may already be open, so we don't need to
37+ // click it again.
38+ if ( await isAccordionClosed ( browser , href ) ) {
39+ const button = await browser . elementByCss ( `${ selector } button` )
40+ await button . click ( )
41+ }
42+
43+ // Click the actual link
44+ const link = await browser . elementByCss ( `${ selector } a` )
45+ await link . click ( )
46+ }
47+
1048 /**
1149 * Create a browser with router act that will FAIL if any 404s occur during navigation.
1250 * This is critical because if a 404 occurs, the client will perform MPA navigation
@@ -27,7 +65,7 @@ describe('interception-dynamic-segment', () => {
2765 it ( 'should work when interception route is paired with a dynamic segment' , async ( ) => {
2866 const browser = await next . browser ( '/' )
2967
30- await browser . elementByCss ( '[href=" /foo/1"]' ) . click ( )
68+ await navigate ( browser , ' /foo/1' )
3169 await browser . waitForIdleNetwork ( )
3270
3371 await retry ( async ( ) => {
@@ -52,7 +90,7 @@ describe('interception-dynamic-segment', () => {
5290 const browser = await next . browser ( '/' )
5391
5492 // Navigate with interception
55- await browser . elementByCss ( '[href=" /foo/1"]' ) . click ( )
93+ await navigate ( browser , ' /foo/1' )
5694 await browser . waitForIdleNetwork ( )
5795
5896 await retry ( async ( ) => {
@@ -82,7 +120,7 @@ describe('interception-dynamic-segment', () => {
82120 const browser = await next . browser ( '/' )
83121
84122 for ( let i = 0 ; i < 2 ; i ++ ) {
85- await browser . elementByCss ( '[href=" /foo/1"]' ) . click ( )
123+ await navigate ( browser , ' /foo/1' )
86124 await browser . waitForIdleNetwork ( )
87125
88126 await retry ( async ( ) => {
@@ -126,7 +164,7 @@ describe('interception-dynamic-segment', () => {
126164 const { act, browser } = await createBrowserWithRouterAct ( '/' )
127165
128166 await act ( async ( ) => {
129- await browser . elementByCss ( '[href=" /foo/1"]' ) . click ( )
167+ await navigate ( browser , ' /foo/1' )
130168 } )
131169
132170 await retry ( async ( ) => {
@@ -145,7 +183,7 @@ describe('interception-dynamic-segment', () => {
145183 const { act, browser } = await createBrowserWithRouterAct ( '/' )
146184
147185 await act ( async ( ) => {
148- await browser . elementByCss ( '[href=" /simple-page"]' ) . click ( )
186+ await navigate ( browser , ' /simple-page' )
149187 } )
150188
151189 await retry ( async ( ) => {
@@ -165,7 +203,7 @@ describe('interception-dynamic-segment', () => {
165203 const { act, browser } = await createBrowserWithRouterAct ( '/' )
166204
167205 await act ( async ( ) => {
168- await browser . elementByCss ( '[href=" /has-page"]' ) . click ( )
206+ await navigate ( browser , ' /has-page' )
169207 } )
170208
171209 await retry ( async ( ) => {
@@ -185,9 +223,7 @@ describe('interception-dynamic-segment', () => {
185223 const { act, browser } = await createBrowserWithRouterAct ( '/' )
186224
187225 await act ( async ( ) => {
188- await browser
189- . elementByCss ( '[href="/no-parallel-routes/deeper"]' )
190- . click ( )
226+ await navigate ( browser , '/no-parallel-routes/deeper' )
191227 } )
192228
193229 await retry ( async ( ) => {
@@ -207,7 +243,7 @@ describe('interception-dynamic-segment', () => {
207243 const { act, browser } = await createBrowserWithRouterAct ( '/' )
208244
209245 await act ( async ( ) => {
210- await browser . elementByCss ( '[href=" /has-both"]' ) . click ( )
246+ await navigate ( browser , ' /has-both' )
211247 } )
212248
213249 await retry ( async ( ) => {
@@ -235,7 +271,7 @@ describe('interception-dynamic-segment', () => {
235271 const { act, browser } = await createBrowserWithRouterAct ( '/' )
236272
237273 await act ( async ( ) => {
238- await browser . elementByCss ( '[href=" /test-nested"]' ) . click ( )
274+ await navigate ( browser , ' /test-nested' )
239275 } )
240276
241277 await retry ( async ( ) => {
@@ -260,7 +296,7 @@ describe('interception-dynamic-segment', () => {
260296
261297 // Navigate directly to the deeper page from home
262298 await act ( async ( ) => {
263- await browser . elementByCss ( '[href=" /test-nested/deeper"]' ) . click ( )
299+ await navigate ( browser , ' /test-nested/deeper' )
264300 } )
265301
266302 await retry ( async ( ) => {
@@ -290,7 +326,7 @@ describe('interception-dynamic-segment', () => {
290326 const { act, browser } = await createBrowserWithRouterAct ( '/' )
291327
292328 await act ( async ( ) => {
293- await browser . elementByCss ( '[href=" /explicit-layout/deeper"]' ) . click ( )
329+ await navigate ( browser , ' /explicit-layout/deeper' )
294330 } )
295331
296332 await retry ( async ( ) => {
@@ -310,12 +346,18 @@ describe('interception-dynamic-segment', () => {
310346 const { act, browser } = await createBrowserWithRouterAct ( '/' )
311347
312348 for ( let i = 0 ; i < 3 ; i ++ ) {
349+ const isAccordionOpen = i > 0
350+
351+ await expect (
352+ isAccordionClosed ( browser , '/test-nested' )
353+ ) . resolves . toBe ( ! isAccordionOpen )
354+
313355 // Forward navigation: triggers RSC request (validates no 404)
314356 await act (
315357 async ( ) => {
316- await browser . elementByCss ( '[href=" /test-nested"]' ) . click ( )
358+ await navigate ( browser , ' /test-nested' )
317359 } ,
318- i > 0 ? 'no-requests' : undefined
360+ ! isAccordionOpen ? undefined : 'no-requests'
319361 )
320362
321363 await retry ( async ( ) => {
@@ -343,7 +385,7 @@ describe('interception-dynamic-segment', () => {
343385
344386 // First interception
345387 await act ( async ( ) => {
346- await browser . elementByCss ( '[href=" /test-nested"]' ) . click ( )
388+ await navigate ( browser , ' /test-nested' )
347389 } )
348390
349391 await retry ( async ( ) => {
@@ -353,8 +395,8 @@ describe('interception-dynamic-segment', () => {
353395
354396 // Second interception
355397 await act ( async ( ) => {
356- await browser . elementByCss ( '[href=" /has-both"]' ) . click ( )
357- } , 'no-requests' )
398+ await navigate ( browser , ' /has-both' )
399+ } )
358400
359401 await retry ( async ( ) => {
360402 const modalContent = await browser . elementByCss ( '#modal' ) . text ( )
0 commit comments