]> git.ipfire.org Git - thirdparty/vuejs/router.git/commitdiff
fix(html5): correctly preserve current history.state
authorEduardo San Martin Morote <posva13@gmail.com>
Mon, 20 Apr 2020 13:03:21 +0000 (15:03 +0200)
committerEduardo San Martin Morote <posva13@gmail.com>
Mon, 20 Apr 2020 13:03:21 +0000 (15:03 +0200)
Fix #180

__tests__/initialNavigation.spec.ts [new file with mode: 0644]
__tests__/utils.ts
src/history/html5.ts

diff --git a/__tests__/initialNavigation.spec.ts b/__tests__/initialNavigation.spec.ts
new file mode 100644 (file)
index 0000000..9857126
--- /dev/null
@@ -0,0 +1,91 @@
+import { JSDOM } from 'jsdom'
+import { createRouter, createWebHistory, Router } from '../src'
+import { createDom, components } from './utils'
+import { RouteRecordRaw } from '../src/types'
+
+// override the value of isBrowser because the variable is created before JSDOM
+// is created
+jest.mock('../src/utils/env', () => ({
+  isBrowser: true,
+}))
+
+// generic component because we are not displaying anything so it doesn't matter
+const component = components.Home
+
+const routes: RouteRecordRaw[] = [
+  { path: '/home', redirect: '/' },
+  { path: '/', component },
+  {
+    path: '/home-before',
+    component,
+    beforeEnter: (to, from, next) => {
+      next('/')
+    },
+  },
+  { path: '/bar', component },
+  { path: '/foo', component, name: 'Foo' },
+  { path: '/to-foo', redirect: '/foo' },
+]
+
+describe('Initial Navigation', () => {
+  let dom: JSDOM
+  function newRouter(
+    url: string,
+    options: Partial<Parameters<typeof createRouter>[0]> = {}
+  ) {
+    dom.reconfigure({ url: 'https://example.com' + url })
+    const history = options.history || createWebHistory()
+    const router = createRouter({ history, routes, ...options })
+
+    return { history, router }
+  }
+
+  function nextNavigation(router: Router) {
+    return new Promise((resolve, reject) => {
+      let removeAfter = router.afterEach((_to, _from, failure) => {
+        removeAfter()
+        removeError()
+        resolve(failure)
+      })
+      let removeError = router.onError(err => {
+        removeAfter()
+        removeError()
+        reject(err)
+      })
+    })
+  }
+
+  beforeAll(() => {
+    dom = createDom()
+  })
+
+  afterAll(() => {
+    dom.window.close()
+  })
+
+  it('handles initial navigation with redirect', async () => {
+    const { history, router } = newRouter('/home')
+    expect(history.location.fullPath).toBe('/home')
+    // this is done automatically on mount but there is no mount here
+    await router.push(history.location.fullPath)
+    expect(router.currentRoute.value).toMatchObject({ path: '/' })
+    await router.push('/foo')
+    expect(router.currentRoute.value).toMatchObject({ path: '/foo' })
+    history.go(-1)
+    await nextNavigation(router)
+    expect(router.currentRoute.value).toMatchObject({ path: '/' })
+  })
+
+  it('handles initial navigation with beforEnter', async () => {
+    const { history, router } = newRouter('/home-before')
+    expect(history.location.fullPath).toBe('/home-before')
+    // this is done automatically on mount but there is no mount here
+    await router.push(history.location.fullPath)
+    expect(router.currentRoute.value).toMatchObject({ path: '/' })
+    await router.push('/foo')
+    expect(router.currentRoute.value).toMatchObject({ path: '/foo' })
+    history.go(-1)
+    await nextNavigation(router)
+    expect(router.currentRoute.value).toMatchObject({ path: '/' })
+  })
+})
index fa92343513900962c27cfd9cb64f16299b18a827..0dd5b3657aba2590a9c6befccaf30996821ffbd0 100644 (file)
@@ -62,6 +62,7 @@ declare global {
     interface Global {
       window: JSDOM['window']
       location: JSDOM['window']['location']
+      history: JSDOM['window']['history']
       document: JSDOM['window']['document']
       before?: Function
     }
@@ -81,6 +82,7 @@ export function createDom(options?: ConstructorOptions) {
 
   global.window = dom.window
   global.location = dom.window.location
+  global.history = dom.window.history
   global.document = dom.window.document
 
   return dom
index 99d028751e13d6349de7079d46e31554c80ce6d8..58878b562f630de843cd60daa800603580cb700e 100644 (file)
@@ -215,6 +215,7 @@ function useHistoryStateNavigation(base: string) {
     const normalized = normalizeHistoryLocation(to)
 
     const state: StateEntry = {
+      ...history.state,
       ...buildState(
         historyState.value.back,
         // keep back and forward entries but override current position
@@ -222,7 +223,6 @@ function useHistoryStateNavigation(base: string) {
         historyState.value.forward,
         true
       ),
-      ...history.state,
       ...data,
       position: historyState.value.position,
     }