--- /dev/null
+import { JSDOM } from 'jsdom'
+import createWebHashHistory from '../../src/history/hash'
+import createWebHistory from '../../src/history/html5'
+import { createDom } from '../utils'
+
+jest.mock('../../src/history/html5')
+
+describe('History Hash', () => {
+ let dom: JSDOM
+ beforeAll(() => {
+ dom = createDom()
+ })
+
+ beforeEach(() => {
+ ;(createWebHistory as jest.Mock).mockClear()
+ })
+
+ 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()
+ })
+
+ describe('url', () => {
+ beforeEach(() => {
+ dom.reconfigure({ url: 'https://example.com' })
+ })
+
+ it('should use a correct', () => {
+ createWebHashHistory()
+ expect(createWebHistory).toHaveBeenCalledWith('/#')
+ })
+
+ it('should be able to provide a base', () => {
+ createWebHashHistory('/folder/')
+ expect(createWebHistory).toHaveBeenCalledWith('/folder/#')
+ })
+
+ it('should be able to provide a base with no trailing slash', () => {
+ createWebHashHistory('/folder')
+ expect(createWebHistory).toHaveBeenCalledWith('/folder/#')
+ })
+
+ it('should read the base tag', () => {
+ const baseEl = document.createElement('base')
+ baseEl.href = '/foo/'
+ document.head.appendChild(baseEl)
+ createWebHashHistory()
+ expect(createWebHistory).toHaveBeenCalledWith('/foo/#')
+ })
+
+ it('should use the base option over the base tag', () => {
+ const baseEl = document.createElement('base')
+ baseEl.href = '/foo/'
+ document.head.appendChild(baseEl)
+ createWebHashHistory('/bar/')
+ expect(createWebHistory).toHaveBeenCalledWith('/bar/#')
+ })
+ })
+
+ describe('file://', () => {
+ beforeEach(() => {
+ dom.reconfigure({ url: 'file:///usr/some-file.html' })
+ })
+
+ it('should use a correct base', () => {
+ createWebHashHistory()
+ // both, a trailing / and none work
+ expect(createWebHistory).toHaveBeenCalledWith(
+ expect.stringMatching(/^#\/?$/)
+ )
+ })
+
+ it.todo('warns if we provide a base with file://')
+ })
+})
expect(createWebHistory('/foo/').base).toBe('/foo')
expect(createWebHistory('/foo').base).toBe('/foo')
})
+
+ it('handles a single hash base', () => {
+ expect(createWebHistory('#').base).toBe('#')
+ expect(createWebHistory('#/').base).toBe('#')
+ })
+
+ it('handles a non-empty hash base', () => {
+ expect(createWebHistory('#/bar').base).toBe('#/bar')
+ expect(createWebHistory('#/bar/').base).toBe('#/bar')
+ })
})
fullPath: (location as HistoryLocation).fullPath || (location as string),
}
}
+
+/**
+ * Normalizes a base by removing any trailing slash and reading the base tag if
+ * present.
+ *
+ * @param base base to normalize
+ */
+export 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 avoid leading
+ // slash with hash because the file could be read from the disk like file://
+ // and the leading slash would cause problems
+ if (base.charAt(0) !== '/' && 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(/\/$/, '')
+}
-import { RouterHistory } from './common'
+import { RouterHistory, normalizeBase } from './common'
import createWebHistory from './html5'
-export default function createWebHashHistory(base: string = ''): RouterHistory {
+export default function createWebHashHistory(base?: string): RouterHistory {
// Make sure this implementation is fine in terms of encoding, specially for IE11
- return createWebHistory(base + '/#')
+ return createWebHistory(location.host ? normalizeBase(base) + '/#' : '#')
}
HistoryState,
RawHistoryLocation,
ValueContainer,
+ normalizeBase,
} from './common'
import { computeScrollPosition, ScrollToPosition } from '../utils/scroll'
import { warn } from 'vue'
}
}
-/**
- * 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)