Skip to content

Commit 9d741d0

Browse files
committed
test: Add flush after navigate test
1 parent 48bf791 commit 9d741d0

19 files changed

+186
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { testFlushAfterNavigate } from 'e2e-shared/specs/flush-after-navigate.cy'
2+
3+
testFlushAfterNavigate({
4+
path: '/app/flush-after-navigate',
5+
nextJsRouter: 'app'
6+
})
7+
8+
testFlushAfterNavigate({
9+
path: '/pages/flush-after-navigate',
10+
nextJsRouter: 'pages'
11+
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { FlushAfterNavigateEnd } from 'e2e-shared/specs/flush-after-navigate'
2+
import { Suspense } from 'react'
3+
4+
export default function Page() {
5+
return (
6+
<Suspense>
7+
<FlushAfterNavigateEnd />
8+
</Suspense>
9+
)
10+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { FlushAfterNavigateStart } from 'e2e-shared/specs/flush-after-navigate'
2+
import { Suspense } from 'react'
3+
4+
export default function Page() {
5+
return (
6+
<Suspense>
7+
<FlushAfterNavigateStart path="/app/flush-after-navigate" />
8+
</Suspense>
9+
)
10+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import { FlushAfterNavigateEnd } from 'e2e-shared/specs/flush-after-navigate'
2+
3+
export default FlushAfterNavigateEnd
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { FlushAfterNavigateStart } from 'e2e-shared/specs/flush-after-navigate'
2+
3+
export default function Page() {
4+
return <FlushAfterNavigateStart path="/pages/flush-after-navigate" />
5+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import { testFlushAfterNavigate } from 'e2e-shared/specs/flush-after-navigate.cy'
2+
3+
testFlushAfterNavigate({ path: '/flush-after-navigate' })

packages/e2e/react-router/v6/src/react-router.tsx

+2
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ const router = createBrowserRouter(
4949
<Route path="pretty-urls" lazy={load(import('./routes/pretty-urls'))} />
5050
<Route path="dynamic-segments/dynamic/:segment" lazy={load(import('./routes/dynamic-segments.dynamic.$segment'))} />
5151
<Route path="dynamic-segments/catch-all?*" lazy={load(import('./routes/dynamic-segments.catch-all.$'))} />
52+
<Route path="flush-after-navigate/start" lazy={load(import('./routes/flush-after-navigate.start'))} />
53+
<Route path="flush-after-navigate/end" lazy={load(import('./routes/flush-after-navigate.end'))} />
5254

5355
<Route path="render-count/:hook/:shallow/:history/:startTransition/no-loader" lazy={load(import('./routes/render-count.$hook.$shallow.$history.$startTransition.no-loader'))} />
5456
<Route path="render-count/:hook/:shallow/:history/:startTransition/sync-loader" lazy={load(import('./routes/render-count.$hook.$shallow.$history.$startTransition.sync-loader'))} />
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import { FlushAfterNavigateEnd } from 'e2e-shared/specs/flush-after-navigate'
2+
3+
export default FlushAfterNavigateEnd
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { FlushAfterNavigateStart } from 'e2e-shared/specs/flush-after-navigate'
2+
3+
export default function Page() {
4+
return <FlushAfterNavigateStart path="/flush-after-navigate" />
5+
}

packages/e2e/react-router/v7/app/routes.ts

+2
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ export default [
3232
route('/pretty-urls', './routes/pretty-urls.tsx'),
3333
route('/dynamic-segments/dynamic/:segment', './routes/dynamic-segments.dynamic.$segment.tsx'),
3434
route('/dynamic-segments/catch-all?/*', './routes/dynamic-segments.catch-all.$.tsx'),
35+
route('/flush-after-navigate/start', './routes/flush-after-navigate.start.tsx'),
36+
route('/flush-after-navigate/end', './routes/flush-after-navigate.end.tsx'),
3537

3638
route('/render-count/:hook/:shallow/:history/:startTransition/no-loader', './routes/render-count.$hook.$shallow.$history.$startTransition.no-loader.tsx'),
3739
route('/render-count/:hook/:shallow/:history/:startTransition/sync-loader', './routes/render-count.$hook.$shallow.$history.$startTransition.sync-loader.tsx'),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import { FlushAfterNavigateEnd } from 'e2e-shared/specs/flush-after-navigate'
2+
3+
export default FlushAfterNavigateEnd
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { FlushAfterNavigateStart } from 'e2e-shared/specs/flush-after-navigate'
2+
3+
export default function Page() {
4+
return <FlushAfterNavigateStart path="/flush-after-navigate" />
5+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import { testFlushAfterNavigate } from 'e2e-shared/specs/flush-after-navigate.cy'
2+
3+
testFlushAfterNavigate({ path: '/flush-after-navigate' })
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import { FlushAfterNavigateEnd } from 'e2e-shared/specs/flush-after-navigate'
2+
3+
export default FlushAfterNavigateEnd
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { FlushAfterNavigateStart } from 'e2e-shared/specs/flush-after-navigate'
2+
3+
export default function Page() {
4+
return <FlushAfterNavigateStart path="/flush-after-navigate" />
5+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import { testFlushAfterNavigate } from 'e2e-shared/specs/flush-after-navigate.cy'
2+
3+
testFlushAfterNavigate({ path: '/flush-after-navigate' })
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { createTest } from '../create-test'
2+
import { getUrl } from './flush-after-navigate.defs'
3+
4+
export const testFlushAfterNavigate = createTest(
5+
'Flush after navigate',
6+
({ path }) => {
7+
it('should apply pending search params after navigation', () => {
8+
cy.visit(getUrl(path + '/start', { debounce: 200 }))
9+
cy.contains('#hydration-marker', 'hydrated').should('be.hidden')
10+
cy.get('#test').click()
11+
cy.get('a').click()
12+
cy.location('pathname').should('eq', path + '/end')
13+
cy.get('#client-state').should('have.text', 'pass')
14+
cy.location('search').should('be.empty')
15+
cy.location('search').should('eq', '?test=pass') // Then it flushes
16+
})
17+
it('should apply pending search params on top of existing link state in navigation', () => {
18+
cy.visit(getUrl(path + '/start', { debounce: 200, linkState: 'nav' }))
19+
cy.contains('#hydration-marker', 'hydrated').should('be.hidden')
20+
cy.get('#test').click()
21+
cy.get('a').click()
22+
cy.location('pathname').should('eq', path + '/end')
23+
cy.get('#client-state').should('have.text', 'pass')
24+
cy.location('search').should('eq', '?test=nav')
25+
cy.location('search').should('eq', '?test=pass') // Then it flushes
26+
})
27+
it('should apply pending search params queued while throttled after navigation', () => {
28+
cy.visit(getUrl(path + '/start', { throttle: 200 }))
29+
cy.contains('#hydration-marker', 'hydrated').should('be.hidden')
30+
cy.get('#preflush').click() // Trigger an immediate flush to enable the throttling queue
31+
cy.get('#test').click() // Queue the change
32+
cy.get('a').click() // Navigate
33+
cy.location('pathname').should('eq', path + '/end')
34+
cy.get('#client-state').should('have.text', 'pass')
35+
cy.location('search').should('be.empty')
36+
cy.location('search').should('eq', '?test=pass') // Then it flushes again
37+
})
38+
it('should apply pending search params queued while throttled after navigation with link state', () => {
39+
cy.visit(getUrl(path + '/start', { throttle: 200, linkState: 'nav' }))
40+
cy.contains('#hydration-marker', 'hydrated').should('be.hidden')
41+
cy.get('#preflush').click() // Trigger an immediate flush to enable the throttling queue
42+
cy.get('#test').click() // Queue the change
43+
cy.get('a').click() // Navigate
44+
cy.location('pathname').should('eq', path + '/end')
45+
cy.get('#client-state').should('have.text', 'pass')
46+
cy.location('search').should('eq', '?test=nav')
47+
cy.location('search').should('eq', '?test=pass') // Then it flushes again
48+
})
49+
}
50+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import {
2+
createLoader,
3+
createSerializer,
4+
parseAsInteger,
5+
parseAsString
6+
} from 'nuqs/server'
7+
8+
export const searchParams = {
9+
debounce: parseAsInteger,
10+
throttle: parseAsInteger,
11+
linkState: parseAsString
12+
}
13+
14+
export const loadSearchParams = createLoader(searchParams)
15+
export const getUrl = createSerializer(searchParams)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
'use client'
2+
3+
import {
4+
createSerializer,
5+
parseAsString,
6+
useQueryState,
7+
useQueryStates
8+
} from 'nuqs'
9+
import { Display } from '../components/display'
10+
import { useLink } from '../components/link'
11+
import { searchParams } from './flush-after-navigate.defs'
12+
13+
const getLink = createSerializer({
14+
test: parseAsString
15+
})
16+
17+
export function FlushAfterNavigateStart({ path }: { path: string }) {
18+
const [{ debounce, throttle, linkState }] = useQueryStates(searchParams)
19+
const Link = useLink()
20+
const [, preflush] = useQueryState('preflush')
21+
const [, setState] = useQueryState('test', {
22+
limitUrlUpdates:
23+
debounce !== null
24+
? { method: 'debounce', timeMs: debounce }
25+
: throttle !== null
26+
? { method: 'throttle', timeMs: throttle }
27+
: undefined
28+
})
29+
return (
30+
<>
31+
<button id="test" onClick={() => setState('pass')}>
32+
Test
33+
</button>
34+
<button id="preflush" onClick={() => preflush(null)}>
35+
Preflush
36+
</button>
37+
<Link href={getLink(`${path}/end`, { test: linkState })}>Link</Link>
38+
</>
39+
)
40+
}
41+
42+
export function FlushAfterNavigateEnd() {
43+
const [state] = useQueryState('test')
44+
return <Display environment="client" state={state} />
45+
}

0 commit comments

Comments
 (0)