From 2a173bcd58291bc172e80a8a4021c78aa4da3987 Mon Sep 17 00:00:00 2001 From: devjiwonchoi Date: Mon, 20 May 2024 19:34:35 +0900 Subject: [PATCH 1/5] test: add test from reproduction --- .../prefetch-searchparam/app/layout.tsx | 7 +++++ .../app-dir/prefetch-searchparam/app/page.tsx | 22 +++++++++++++++ .../prefetch-searchparam/next.config.js | 6 +++++ .../prefetch-searchparam.test.ts | 27 +++++++++++++++++++ 4 files changed, 62 insertions(+) create mode 100644 test/e2e/app-dir/prefetch-searchparam/app/layout.tsx create mode 100644 test/e2e/app-dir/prefetch-searchparam/app/page.tsx create mode 100644 test/e2e/app-dir/prefetch-searchparam/next.config.js create mode 100644 test/e2e/app-dir/prefetch-searchparam/prefetch-searchparam.test.ts diff --git a/test/e2e/app-dir/prefetch-searchparam/app/layout.tsx b/test/e2e/app-dir/prefetch-searchparam/app/layout.tsx new file mode 100644 index 0000000000000..e7077399c03ce --- /dev/null +++ b/test/e2e/app-dir/prefetch-searchparam/app/layout.tsx @@ -0,0 +1,7 @@ +export default function Root({ children }: { children: React.ReactNode }) { + return ( + + {children} + + ) +} diff --git a/test/e2e/app-dir/prefetch-searchparam/app/page.tsx b/test/e2e/app-dir/prefetch-searchparam/app/page.tsx new file mode 100644 index 0000000000000..33c880d73ec1a --- /dev/null +++ b/test/e2e/app-dir/prefetch-searchparam/app/page.tsx @@ -0,0 +1,22 @@ +import Link from 'next/link' + +export default async function Page({ + searchParams, +}: { + searchParams: { [key: string]: string | string[] | undefined } +}) { + return ( +
+ + 1: Click here and refresh page (?foo=bar1) + + + 2. Click here (?foo=bar2) + + + 3. Click here wtf (/) + +

{JSON.stringify(searchParams)}

+
+ ) +} diff --git a/test/e2e/app-dir/prefetch-searchparam/next.config.js b/test/e2e/app-dir/prefetch-searchparam/next.config.js new file mode 100644 index 0000000000000..807126e4cf0bf --- /dev/null +++ b/test/e2e/app-dir/prefetch-searchparam/next.config.js @@ -0,0 +1,6 @@ +/** + * @type {import('next').NextConfig} + */ +const nextConfig = {} + +module.exports = nextConfig diff --git a/test/e2e/app-dir/prefetch-searchparam/prefetch-searchparam.test.ts b/test/e2e/app-dir/prefetch-searchparam/prefetch-searchparam.test.ts new file mode 100644 index 0000000000000..35c7113010df3 --- /dev/null +++ b/test/e2e/app-dir/prefetch-searchparam/prefetch-searchparam.test.ts @@ -0,0 +1,27 @@ +import { nextTestSetup } from 'e2e-utils' + +describe('prefetch-searchparam', () => { + const { next } = nextTestSetup({ + files: __dirname, + }) + // Recommended for tests that need a full browser + it('should work using browser', async () => { + const browser = await next.browser('/') + expect(await browser.elementByCss('p').text()).toBe('{}') + + await browser.elementByCss('[id="1"]').click() + await browser.waitForElementByCss('p', 5000) + expect(await browser.elementByCss('p').text()).toBe('{"foo":"bar1"}') + + // refresh the page + await browser.refresh() + + await browser.elementByCss('[id="2"]').click() + await browser.waitForElementByCss('p', 5000) + expect(await browser.elementByCss('p').text()).toBe('{"foo":"bar2"}') + + await browser.elementByCss('[id="3"]').click() + await browser.waitForElementByCss('p', 5000) + expect(await browser.elementByCss('p').text()).toBe('{}') + }) +}) From f8bd21cd185e11140fc5dc0e58ff0a47dcd360d3 Mon Sep 17 00:00:00 2001 From: devjiwonchoi Date: Mon, 20 May 2024 20:09:54 +0900 Subject: [PATCH 2/5] test: update --- .../app-dir/prefetch-searchparam/app/page.tsx | 21 +++++-------------- .../prefetch-searchparam.test.ts | 21 +++++++------------ 2 files changed, 13 insertions(+), 29 deletions(-) diff --git a/test/e2e/app-dir/prefetch-searchparam/app/page.tsx b/test/e2e/app-dir/prefetch-searchparam/app/page.tsx index 33c880d73ec1a..932fdc612a540 100644 --- a/test/e2e/app-dir/prefetch-searchparam/app/page.tsx +++ b/test/e2e/app-dir/prefetch-searchparam/app/page.tsx @@ -1,22 +1,11 @@ import Link from 'next/link' -export default async function Page({ - searchParams, -}: { - searchParams: { [key: string]: string | string[] | undefined } -}) { +export default function Page({ searchParams }: { searchParams: any }) { return ( -
- - 1: Click here and refresh page (?foo=bar1) - - - 2. Click here (?foo=bar2) - - - 3. Click here wtf (/) - + <> + / + /?q=bar

{JSON.stringify(searchParams)}

-
+ ) } diff --git a/test/e2e/app-dir/prefetch-searchparam/prefetch-searchparam.test.ts b/test/e2e/app-dir/prefetch-searchparam/prefetch-searchparam.test.ts index 35c7113010df3..8f1709b7d9005 100644 --- a/test/e2e/app-dir/prefetch-searchparam/prefetch-searchparam.test.ts +++ b/test/e2e/app-dir/prefetch-searchparam/prefetch-searchparam.test.ts @@ -4,23 +4,18 @@ describe('prefetch-searchparam', () => { const { next } = nextTestSetup({ files: __dirname, }) - // Recommended for tests that need a full browser it('should work using browser', async () => { - const browser = await next.browser('/') - expect(await browser.elementByCss('p').text()).toBe('{}') - - await browser.elementByCss('[id="1"]').click() - await browser.waitForElementByCss('p', 5000) - expect(await browser.elementByCss('p').text()).toBe('{"foo":"bar1"}') - - // refresh the page - await browser.refresh() + // load with search param + const browser = await next.browser('/?q=foo') + expect(await browser.elementByCss('p').text()).toBe('{"q":"foo"}') - await browser.elementByCss('[id="2"]').click() + // navigate to different search param, should update the search param + await browser.elementByCss('[href="/?q=bar"]').click() await browser.waitForElementByCss('p', 5000) - expect(await browser.elementByCss('p').text()).toBe('{"foo":"bar2"}') + expect(await browser.elementByCss('p').text()).toBe('{"q":"bar"}') - await browser.elementByCss('[id="3"]').click() + // navigate to home, should clear the search param + await browser.elementByCss('[href="/"]').click() await browser.waitForElementByCss('p', 5000) expect(await browser.elementByCss('p').text()).toBe('{}') }) From 48e597499c5e5fa5af329d1d2fdfffb2e13e5e07 Mon Sep 17 00:00:00 2001 From: devjiwonchoi Date: Mon, 20 May 2024 20:25:54 +0900 Subject: [PATCH 3/5] fix: add search param for prefetch cache --- .../components/router-reducer/create-initial-router-state.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/next/src/client/components/router-reducer/create-initial-router-state.ts b/packages/next/src/client/components/router-reducer/create-initial-router-state.ts index 9a8b5bc901dc6..e3a2cbcdd832e 100644 --- a/packages/next/src/client/components/router-reducer/create-initial-router-state.ts +++ b/packages/next/src/client/components/router-reducer/create-initial-router-state.ts @@ -101,7 +101,10 @@ export function createInitialRouterState({ // Seed the prefetch cache with this page's data. // This is to prevent needlessly re-prefetching a page that is already reusable, // and will avoid triggering a loading state/data fetch stall when navigating back to the page. - const url = new URL(location.pathname, location.origin) + const url = new URL( + `${location.pathname}${location.search}`, + location.origin + ) const initialFlightData: FlightData = [['', initialTree, null, null]] createPrefetchCacheEntryForInitialLoad({ From 5b0af4a756b3292a99afbc865591e6024a25299a Mon Sep 17 00:00:00 2001 From: devjiwonchoi Date: Mon, 20 May 2024 20:27:48 +0900 Subject: [PATCH 4/5] test: add details --- .../prefetch-searchparam/prefetch-searchparam.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/e2e/app-dir/prefetch-searchparam/prefetch-searchparam.test.ts b/test/e2e/app-dir/prefetch-searchparam/prefetch-searchparam.test.ts index 8f1709b7d9005..c122c412edf49 100644 --- a/test/e2e/app-dir/prefetch-searchparam/prefetch-searchparam.test.ts +++ b/test/e2e/app-dir/prefetch-searchparam/prefetch-searchparam.test.ts @@ -4,8 +4,8 @@ describe('prefetch-searchparam', () => { const { next } = nextTestSetup({ files: __dirname, }) - it('should work using browser', async () => { - // load with search param + it('should set prefetch cache properly on different search params', async () => { + // load WITH search param const browser = await next.browser('/?q=foo') expect(await browser.elementByCss('p').text()).toBe('{"q":"foo"}') @@ -14,7 +14,7 @@ describe('prefetch-searchparam', () => { await browser.waitForElementByCss('p', 5000) expect(await browser.elementByCss('p').text()).toBe('{"q":"bar"}') - // navigate to home, should clear the search param + // navigate to home, should clear the searchParams value await browser.elementByCss('[href="/"]').click() await browser.waitForElementByCss('p', 5000) expect(await browser.elementByCss('p').text()).toBe('{}') From 13b0861187a85807bb1e9ca95f0cb249218bdadb Mon Sep 17 00:00:00 2001 From: Zack Tanner <1939140+ztanner@users.noreply.github.com> Date: Mon, 20 May 2024 08:08:03 -0700 Subject: [PATCH 5/5] de-flake test --- .../prefetch-searchparam/prefetch-searchparam.test.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/test/e2e/app-dir/prefetch-searchparam/prefetch-searchparam.test.ts b/test/e2e/app-dir/prefetch-searchparam/prefetch-searchparam.test.ts index c122c412edf49..594c690aa5d32 100644 --- a/test/e2e/app-dir/prefetch-searchparam/prefetch-searchparam.test.ts +++ b/test/e2e/app-dir/prefetch-searchparam/prefetch-searchparam.test.ts @@ -1,4 +1,5 @@ import { nextTestSetup } from 'e2e-utils' +import { retry } from 'next-test-utils' describe('prefetch-searchparam', () => { const { next } = nextTestSetup({ @@ -11,12 +12,14 @@ describe('prefetch-searchparam', () => { // navigate to different search param, should update the search param await browser.elementByCss('[href="/?q=bar"]').click() - await browser.waitForElementByCss('p', 5000) - expect(await browser.elementByCss('p').text()).toBe('{"q":"bar"}') + await retry(async () => { + expect(await browser.elementByCss('p').text()).toBe('{"q":"bar"}') + }) // navigate to home, should clear the searchParams value await browser.elementByCss('[href="/"]').click() - await browser.waitForElementByCss('p', 5000) - expect(await browser.elementByCss('p').text()).toBe('{}') + await retry(async () => { + expect(await browser.elementByCss('p').text()).toBe('{}') + }) }) })