]> git.ipfire.org Git - thirdparty/vuejs/router.git/commitdiff
fix(router): allow replace to have query and hash
authorEduardo San Martin Morote <posva13@gmail.com>
Sun, 27 Dec 2020 23:22:39 +0000 (00:22 +0100)
committerEduardo San Martin Morote <posva13@gmail.com>
Sun, 27 Dec 2020 23:22:39 +0000 (00:22 +0100)
fix #668

__tests__/router.spec.ts
src/router.ts

index 84d4206834669483e96544c55ba3af218c36c678..a1303e267bb694af9ae21c70a0e559b742852b53 100644 (file)
@@ -31,6 +31,7 @@ const routes: RouteRecordRaw[] = [
   { path: '/to-foo', redirect: '/foo' },
   { path: '/to-foo-named', redirect: { name: 'Foo' } },
   { path: '/to-foo2', redirect: '/to-foo' },
+  { path: '/to-foo-query', redirect: '/foo?a=2#b' },
   { path: '/to-p/:p', redirect: { name: 'Param' } },
   { path: '/p/:p', name: 'Param', component: components.Bar },
   { path: '/repeat/:r+', name: 'repeat', component: components.Bar },
@@ -115,6 +116,18 @@ describe('Router', () => {
     expect(history.replace).toHaveBeenCalledWith('/foo', expect.anything())
   })
 
+  it('parses query and hash with router.replace', async () => {
+    const history = createMemoryHistory()
+    const { router } = await newRouter({ history })
+    jest.spyOn(history, 'replace')
+    await router.replace('/foo?q=2#a')
+    expect(history.replace).toHaveBeenCalledTimes(1)
+    expect(history.replace).toHaveBeenCalledWith(
+      '/foo?q=2#a',
+      expect.anything()
+    )
+  })
+
   it('replaces if a guard redirects', async () => {
     const history = createMemoryHistory()
     const { router } = await newRouter({ history })
@@ -537,6 +550,22 @@ describe('Router', () => {
       })
     })
 
+    it('handles query and hash passed in redirect string', async () => {
+      const history = createMemoryHistory()
+      const router = createRouter({ history, routes })
+      await expect(router.push('/to-foo-query')).resolves.toEqual(undefined)
+      expect(router.currentRoute.value).toMatchObject({
+        name: 'Foo',
+        path: '/foo',
+        params: {},
+        query: { a: '2' },
+        hash: '#b',
+        redirectedFrom: expect.objectContaining({
+          fullPath: '/to-foo-query',
+        }),
+      })
+    })
+
     it('keeps query and hash when redirect is a string', async () => {
       const history = createMemoryHistory()
       const router = createRouter({ history, routes })
index 5dc4279ba478cea711b8f9ad5a1adcf054f05d1c..d28df79c03129936a382c2a158c42c3bae846dc6 100644 (file)
@@ -522,8 +522,9 @@ export function createRouter(options: RouterOptions): Router {
   function locationAsObject(
     to: RouteLocationRaw | RouteLocationNormalized
   ): Exclude<RouteLocationRaw, string> | RouteLocationNormalized {
-    // FIXME: does not take into account query params
-    return typeof to === 'string' ? { path: to } : assign({}, to)
+    return typeof to === 'string'
+      ? parseURL(parseQuery, to, currentRoute.value.path)
+      : assign({}, to)
   }
 
   function checkCanceledNavigation(
@@ -553,10 +554,16 @@ export function createRouter(options: RouterOptions): Router {
     const lastMatched = to.matched[to.matched.length - 1]
     if (lastMatched && lastMatched.redirect) {
       const { redirect } = lastMatched
-      // transform it into an object to pass the original RouteLocaleOptions
-      let newTargetLocation = locationAsObject(
+      let newTargetLocation =
         typeof redirect === 'function' ? redirect(to) : redirect
-      )
+
+      if (typeof newTargetLocation === 'string') {
+        newTargetLocation =
+          newTargetLocation.indexOf('?') > -1 ||
+          newTargetLocation.indexOf('#') > -1
+            ? (newTargetLocation = locationAsObject(newTargetLocation))
+            : { path: newTargetLocation }
+      }
 
       if (
         __DEV__ &&
@@ -587,9 +594,7 @@ export function createRouter(options: RouterOptions): Router {
   }
 
   function pushWithRedirect(
-    // TODO: should only be RouteLocation?
     to: RouteLocationRaw | RouteLocation,
-    // TODO: add replace here
     redirectedFrom?: RouteLocation
   ): Promise<NavigationFailure | void | undefined> {
     const targetLocation: RouteLocation = (pendingLocation = resolve(to))
@@ -603,7 +608,11 @@ export function createRouter(options: RouterOptions): Router {
 
     if (shouldRedirect)
       return pushWithRedirect(
-        assign(shouldRedirect, { state: data, force, replace }),
+        assign(locationAsObject(shouldRedirect), {
+          state: data,
+          force,
+          replace,
+        }),
         // keep original redirectedFrom if it exists
         redirectedFrom || targetLocation
       )