From b4d3ebf472a8b51b3c8b3f0c0162891987105d8d Mon Sep 17 00:00:00 2001 From: Konstantin Barabanov Date: Tue, 30 Jun 2020 20:16:21 +0300 Subject: [PATCH] fix(vue-app): sanitize path with trailing slash in `getLocation` (#6744) (#6745) --- packages/vue-app/template/utils.js | 3 +- test/e2e/spa-base.browser.test.js | 71 +++++++++++++++++++++++++++ test/fixtures/spa-base/nuxt.config.js | 13 +++++ test/fixtures/spa/spa.test.js | 1 + 4 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 test/e2e/spa-base.browser.test.js create mode 100644 test/fixtures/spa-base/nuxt.config.js diff --git a/packages/vue-app/template/utils.js b/packages/vue-app/template/utils.js index 3aff9e9dfad8..126b584dcaa9 100644 --- a/packages/vue-app/template/utils.js +++ b/packages/vue-app/template/utils.js @@ -282,7 +282,8 @@ export function getLocation (base, mode) { if (mode === 'hash') { return window.location.hash.replace(/^#\//, '') } - if (base && path.indexOf(base) === 0) { + // To get matched with sanitized router.base add trailing slash + if (base && (path.endsWith('/') ? path : path + '/').startsWith(base)) { path = path.slice(base.length) } return (path || '/') + window.location.search + window.location.hash diff --git a/test/e2e/spa-base.browser.test.js b/test/e2e/spa-base.browser.test.js new file mode 100644 index 000000000000..8eac938d7460 --- /dev/null +++ b/test/e2e/spa-base.browser.test.js @@ -0,0 +1,71 @@ +import Browser from '../utils/browser' +import { loadFixture, getPort, Nuxt } from '../utils' + +let port +const browser = new Browser() +const url = route => 'http://localhost:' + port + route + +let nuxt = null +let page = null + +describe('spa router base browser', () => { + beforeAll(async () => { + const config = await loadFixture('spa-base') + nuxt = new Nuxt(config) + await nuxt.ready() + + port = await getPort() + await nuxt.server.listen(port, 'localhost') + + await browser.start({ + // slowMo: 50, + // headless: false + }) + }) + + test('Open /app (router base)', async () => { + page = await browser.page(url('/app')) + + expect(await page.evaluate(() => location.href)).toBe(url('/app')) + + expect(await page.html()).not.toContain('This page could not be found') + + expect(await page.evaluate(() => { + const headings = document.evaluate("//div[text()='Hello SPA!']", document, null, XPathResult.ANY_TYPE, null) + return headings.iterateNext() + })).not.toBe(null) + }) + + test('Open /app/ (router base with trailing slash)', async () => { + page = await browser.page(url('/app/')) + + expect(await page.evaluate(() => location.href)).toBe(url('/app/')) + + expect(await page.html()).not.toContain('This page could not be found') + }) + + test('Open /app/mounted', async () => { + page = await browser.page(url('/app/mounted')) + + expect(await page.$text('h1')).toMatch('Test: updated') + }) + + test('/app/unknown', async () => { + page = await browser.page(url('/app/unknown')) + + expect(await page.evaluate(() => location.href)).toBe(url('/app/unknown')) + + expect(await page.html()).toContain('This page could not be found') + }) + + // Close server and ask nuxt to stop listening to file changes + afterAll(async () => { + await nuxt.close() + }) + + // Stop browser + afterAll(async () => { + await page.close() + await browser.close() + }) +}) diff --git a/test/fixtures/spa-base/nuxt.config.js b/test/fixtures/spa-base/nuxt.config.js new file mode 100644 index 000000000000..e8b342045fb6 --- /dev/null +++ b/test/fixtures/spa-base/nuxt.config.js @@ -0,0 +1,13 @@ +import { resolve } from 'path' +import defaultsDeep from 'lodash/defaultsDeep' +import baseNuxtConfig from '../spa/nuxt.config' + +const config = { + buildDir: resolve(__dirname, '.nuxt'), + srcDir: resolve(__dirname, '..', 'spa'), + router: { + base: '/app' + } +} + +export default defaultsDeep(config, baseNuxtConfig) diff --git a/test/fixtures/spa/spa.test.js b/test/fixtures/spa/spa.test.js index 199675fcbca1..f1a696f9f5ab 100644 --- a/test/fixtures/spa/spa.test.js +++ b/test/fixtures/spa/spa.test.js @@ -4,3 +4,4 @@ import { buildFixture } from '../../utils/build' // That's why building both from same test file. buildFixture('spa') buildFixture('spa-hash') +buildFixture('spa-base')