+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
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')
+ })
})
}
}
-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,
const routerHistory: RouterHistory = {
// it's overridden right after
// @ts-ignore
- location: historyNavigation.location.value,
+ location: '',
base,
back,
forward,