From 5aed1d2e353a1e49db49a69405ab6cd17328743a Mon Sep 17 00:00:00 2001 From: Jan Potoms <2109932+Janpot@users.noreply.github.com> Date: Thu, 10 Sep 2020 17:12:37 +0200 Subject: [PATCH] Correct query behavior for falsey values to pre 9.5.1 behavior (#16608) Fixes https://github.com/vercel/next.js/issues/16147 --- .../lib/router/utils/querystring.ts | 16 ++++++- .../build-output/test/index.test.js | 2 +- .../pages/nav/query-params.js | 43 +++++++++++++++++++ .../client-navigation/pages/query.js | 6 +++ .../client-navigation/test/index.test.js | 20 +++++++++ .../integration/size-limit/test/index.test.js | 2 +- 6 files changed, 85 insertions(+), 4 deletions(-) create mode 100644 test/integration/client-navigation/pages/nav/query-params.js create mode 100644 test/integration/client-navigation/pages/query.js diff --git a/packages/next/next-server/lib/router/utils/querystring.ts b/packages/next/next-server/lib/router/utils/querystring.ts index 27c22afdbef74..f86d7a3c257e6 100644 --- a/packages/next/next-server/lib/router/utils/querystring.ts +++ b/packages/next/next-server/lib/router/utils/querystring.ts @@ -16,15 +16,27 @@ export function searchParamsToUrlQuery( return query } +function stringifyUrlQueryParam(param: string): string { + if ( + typeof param === 'string' || + (typeof param === 'number' && !isNaN(param)) || + typeof param === 'boolean' + ) { + return String(param) + } else { + return '' + } +} + export function urlQueryToSearchParams( urlQuery: ParsedUrlQuery ): URLSearchParams { const result = new URLSearchParams() Object.entries(urlQuery).forEach(([key, value]) => { if (Array.isArray(value)) { - value.forEach((item) => result.append(key, item)) + value.forEach((item) => result.append(key, stringifyUrlQueryParam(item))) } else { - result.set(key, value) + result.set(key, stringifyUrlQueryParam(value)) } }) return result diff --git a/test/integration/build-output/test/index.test.js b/test/integration/build-output/test/index.test.js index 1212e032a21d0..26294e83862fe 100644 --- a/test/integration/build-output/test/index.test.js +++ b/test/integration/build-output/test/index.test.js @@ -104,7 +104,7 @@ describe('Build Output', () => { expect(parseFloat(err404FirstLoad) - 63.6).toBeLessThanOrEqual(0) expect(err404FirstLoad.endsWith('kB')).toBe(true) - expect(parseFloat(sharedByAll) - 60.1).toBeLessThanOrEqual(0) + expect(parseFloat(sharedByAll) - 60.2).toBeLessThanOrEqual(0) expect(sharedByAll.endsWith('kB')).toBe(true) if (_appSize.endsWith('kB')) { diff --git a/test/integration/client-navigation/pages/nav/query-params.js b/test/integration/client-navigation/pages/nav/query-params.js new file mode 100644 index 0000000000000..a56b0187dfa6d --- /dev/null +++ b/test/integration/client-navigation/pages/nav/query-params.js @@ -0,0 +1,43 @@ +import { useRouter } from 'next/router' + +export default function Page() { + const router = useRouter() + return ( + <> + + + ) +} diff --git a/test/integration/client-navigation/pages/query.js b/test/integration/client-navigation/pages/query.js new file mode 100644 index 0000000000000..c2b11b12a40e9 --- /dev/null +++ b/test/integration/client-navigation/pages/query.js @@ -0,0 +1,6 @@ +import { useRouter } from 'next/router' + +export default function Page() { + const router = useRouter() + return
{JSON.stringify(router.query, null, 2)}
+} diff --git a/test/integration/client-navigation/test/index.test.js b/test/integration/client-navigation/test/index.test.js index 1e2c7c8bac347..f3fc7c314dc7e 100644 --- a/test/integration/client-navigation/test/index.test.js +++ b/test/integration/client-navigation/test/index.test.js @@ -801,6 +801,26 @@ describe('Client Navigation', () => { await browser.close() }) + + it('should handle undefined in router.push', async () => { + const browser = await webdriver(context.appPort, '/nav/query-params') + await browser.elementByCss('#click-me').click() + const query = JSON.parse( + await browser.waitForElementByCss('#query-value').text() + ) + expect(query).toEqual({ + param1: '', + param2: '', + param3: '', + param4: '0', + param5: 'false', + param7: '', + param8: '', + param9: '', + param10: '', + param11: ['', '', '', '0', 'false', '', '', '', '', ''], + }) + }) }) describe('with querystring relative urls', () => { diff --git a/test/integration/size-limit/test/index.test.js b/test/integration/size-limit/test/index.test.js index 6bc2f88f42233..69d1d60c16753 100644 --- a/test/integration/size-limit/test/index.test.js +++ b/test/integration/size-limit/test/index.test.js @@ -100,7 +100,7 @@ describe('Production response size', () => { ) // These numbers are without gzip compression! - const delta = responseSizesBytes - 169 * 1024 + const delta = responseSizesBytes - 170 * 1024 expect(delta).toBeLessThanOrEqual(1024) // don't increase size more than 1kb expect(delta).toBeGreaterThanOrEqual(-1024) // don't decrease size more than 1kb without updating target })