From e98a877ee4a182d077cb5ba5e70500ae8bcbf986 Mon Sep 17 00:00:00 2001 From: Luc Date: Thu, 28 Jun 2018 08:37:57 +0200 Subject: [PATCH] Merge url query with exportPathMap (#4678) This PR fixes #4615 From the issue : > One thing we might consider is merging and showing a warning for keys not defined in exportPathMap The behaviour after this PR is the following : ```js // next.config.js module.exports = { exportPathMap: () => ({ '/': { page: '/', query: { a: 'blue' } } }) } ``` | url called | `ctx.query` | warning ? | |-|-|-| | `/` | `{ a: 'blue' }` | | | `/?a=red` | `{ a: 'blue' }` | | | `/?b=green` | `{ a: 'blue', b: 'green' }` | `... parameter 'b' missing in exportPathMap` | Is that the expected behaviour ? If not, I'll update the PR to shape the expected behavior. --- server/index.js | 10 +++++++++- test/integration/static/next.config.js | 3 ++- test/integration/static/pages/query.js | 12 ++++++++++++ test/integration/static/test/dev.js | 27 ++++++++++++++++++++++++++ 4 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 test/integration/static/pages/query.js diff --git a/server/index.js b/server/index.js index 310ab3dc..87f4188d 100644 --- a/server/index.js +++ b/server/index.js @@ -254,7 +254,15 @@ export default class Server { for (const path in exportPathMap) { const {page, query = {}} = exportPathMap[path] routes[path] = async (req, res, params, parsedUrl) => { - await this.render(req, res, page, query, parsedUrl) + const { query: urlQuery } = parsedUrl + + Object.keys(urlQuery) + .filter(key => query[key] === undefined) + .forEach(key => console.warn(`Url defines a query parameter '${key}' that is missing in exportPathMap`)) + + const mergedQuery = {...urlQuery, ...query} + + await this.render(req, res, page, mergedQuery, parsedUrl) } } } diff --git a/test/integration/static/next.config.js b/test/integration/static/next.config.js index fc2c1d2b..6e51f14a 100644 --- a/test/integration/static/next.config.js +++ b/test/integration/static/next.config.js @@ -15,7 +15,8 @@ module.exports = (phase) => { '/dynamic': { page: '/dynamic', query: { text: 'cool dynamic text' } }, '/dynamic/one': { page: '/dynamic', query: { text: 'next export is nice' } }, '/dynamic/two': { page: '/dynamic', query: { text: 'zeit is awesome' } }, - '/file-name.md': { page: '/dynamic', query: { text: 'this file has an extension' } } + '/file-name.md': { page: '/dynamic', query: { text: 'this file has an extension' } }, + '/query': { page: '/query', query: { a: 'blue' } } } } } diff --git a/test/integration/static/pages/query.js b/test/integration/static/pages/query.js new file mode 100644 index 00000000..e5246768 --- /dev/null +++ b/test/integration/static/pages/query.js @@ -0,0 +1,12 @@ +import { Component } from 'react' + +class Page extends Component { + static getInitialProps ({ query }) { + return { query } + } + render () { + return JSON.stringify(this.props.query, null, 2) + } +} + +export default Page diff --git a/test/integration/static/test/dev.js b/test/integration/static/test/dev.js index 468a011b..37dac976 100644 --- a/test/integration/static/test/dev.js +++ b/test/integration/static/test/dev.js @@ -1,5 +1,12 @@ /* global describe, it, expect */ import webdriver from 'next-webdriver' +import { renderViaHTTP } from 'next-test-utils' +import cheerio from 'cheerio' + +const loadJSONInPage = pageContent => { + const page = cheerio.load(pageContent) + return JSON.parse(page('#__next').text()) +} export default function (context) { describe('Render in development mode', () => { @@ -21,4 +28,24 @@ export default function (context) { browser.close() }) }) + + describe(`ExportPathMap's query in development mode`, () => { + it('should be present in ctx.query', async () => { + const pageContent = await renderViaHTTP(context.port, '/query') + const json = loadJSONInPage(pageContent) + expect(json).toEqual({ a: 'blue' }) + }) + + it('should replace url query params in ctx.query when conflicting', async () => { + const pageContent = await renderViaHTTP(context.port, '/query?a=red') + const json = loadJSONInPage(pageContent) + expect(json).toEqual({ a: 'blue' }) + }) + + it('should be merged with url query params in ctx.query', async () => { + const pageContent = await renderViaHTTP(context.port, '/query?b=green') + const json = loadJSONInPage(pageContent) + expect(json).toEqual({ a: 'blue', b: 'green' }) + }) + }) }