]> git.ipfire.org Git - thirdparty/vuejs/router.git/commitdiff
fix(history): allow base with / and base tag
authorEduardo San Martin Morote <posva13@gmail.com>
Mon, 13 Apr 2020 14:20:00 +0000 (16:20 +0200)
committerEduardo San Martin Morote <posva13@gmail.com>
Mon, 13 Apr 2020 14:20:00 +0000 (16:20 +0200)
Close #164

__tests__/history/html5.spec.ts
jest.config.js
src/history/html5.ts

index 606deee16bf8b4784d28a785e00c7f2a9be156bb..e0b48448c120a9d90caeb7777af3a13bd268edfd 100644 (file)
@@ -1,11 +1,24 @@
+import { JSDOM } from 'jsdom'
 import createWebHistory from '../../src/history/html5'
 import { createDom } from '../utils'
 
 // These unit tests are supposed to tests very specific scenarios that are easier to setup
 // on a unit test than an e2e tests
 describe('History HTMl5', () => {
+  let dom: JSDOM
   beforeAll(() => {
-    createDom()
+    dom = createDom()
+  })
+
+  afterAll(() => {
+    dom.window.close()
+  })
+
+  afterEach(() => {
+    // ensure no base element is left after a test as only the first is
+    // respected
+    for (let element of Array.from(document.getElementsByTagName('base')))
+      element.remove()
   })
 
   // this problem is very common on hash history when using a regular link
@@ -17,4 +30,42 @@ describe('History HTMl5', () => {
       fullPath: '/',
     })
   })
+
+  it('handles a basic base', () => {
+    expect(createWebHistory().base).toBe('')
+    expect(createWebHistory('/').base).toBe('')
+  })
+
+  it('handles a base tag', () => {
+    const baseEl = document.createElement('base')
+    baseEl.href = '/foo/'
+    document.head.appendChild(baseEl)
+    expect(createWebHistory().base).toBe('/foo')
+  })
+
+  it('handles a base tag with origin', () => {
+    const baseEl = document.createElement('base')
+    baseEl.href = 'https://example.com/foo/'
+    document.head.appendChild(baseEl)
+    expect(createWebHistory().base).toBe('/foo')
+  })
+
+  it('handles a base tag with origin without trailing slash', () => {
+    const baseEl = document.createElement('base')
+    baseEl.href = 'https://example.com/bar'
+    document.head.appendChild(baseEl)
+    expect(createWebHistory().base).toBe('/bar')
+  })
+
+  it('ignores base tag if base is provided', () => {
+    const baseEl = document.createElement('base')
+    baseEl.href = '/foo/'
+    document.head.appendChild(baseEl)
+    expect(createWebHistory('/bar/').base).toBe('/bar')
+  })
+
+  it('handles a non-empty base', () => {
+    expect(createWebHistory('/foo/').base).toBe('/foo')
+    expect(createWebHistory('/foo').base).toBe('/foo')
+  })
 })
index 63ee84ff53a5e739ef17ae04d4c44b168a594288..7b070c133b22714264e91e04eed5177b6795c441 100644 (file)
@@ -2,6 +2,7 @@ module.exports = {
   preset: 'ts-jest',
   globals: {
     __DEV__: true,
+    __BROWSER__: true,
   },
   coverageDirectory: 'coverage',
   coverageReporters: ['html', 'lcov', 'text'],
index 8475234444570669960324cc69a66d18cb0841bb..8ac97dd4f33b1f9964bca5489615fde269994ed9 100644 (file)
@@ -262,7 +262,36 @@ function useHistoryStateNavigation(base: string) {
   }
 }
 
-export default function createWebHistory(base: string = ''): RouterHistory {
+/**
+ * Normalizes a base by removing any trailing slash and reading the base tag if
+ * present.
+ *
+ * @param base base to normalize
+ */
+function normalizeBase(base?: string): string {
+  if (!base) {
+    if (__BROWSER__) {
+      // respect <base> tag
+      const baseEl = document.querySelector('base')
+      base = (baseEl && baseEl.getAttribute('href')) || '/'
+      // strip full URL origin
+      base = base.replace(/^\w+:\/\/[^\/]+/, '')
+    } else {
+      base = '/'
+    }
+  }
+
+  // ensure leading slash when it was removed by the regex above
+  if (base.charAt(0) !== '/') base = '/' + base
+
+  // remove the trailing slash so all other method can just do `base + fullPath`
+  // to build an href
+  return base.replace(/\/$/, '')
+}
+
+export default function createWebHistory(base?: string): RouterHistory {
+  base = normalizeBase(base)
+
   const historyNavigation = useHistoryStateNavigation(base)
   const historyListeners = useHistoryListeners(
     base,
@@ -283,7 +312,7 @@ export default function createWebHistory(base: string = ''): RouterHistory {
   const routerHistory: RouterHistory = {
     // it's overridden right after
     // @ts-ignore
-    location: historyNavigation.location.value,
+    location: '',
     base,
     back,
     forward,