]> git.ipfire.org Git - thirdparty/vuejs/router.git/commitdiff
feat: throw with invalid redirect
authorEduardo San Martin Morote <posva13@gmail.com>
Mon, 6 May 2019 10:09:42 +0000 (12:09 +0200)
committerEduardo San Martin Morote <posva13@gmail.com>
Mon, 6 May 2019 10:09:42 +0000 (12:09 +0200)
__tests__/matcher.spec.js
src/errors.ts
src/matcher.ts

index f9209839cadd50358cf2a8157435228a4e2c3f16..42a0b9a4a488e2e45e1a8a4b0a551ca7e56168c8 100644 (file)
@@ -358,6 +358,48 @@ describe('Router Matcher', () => {
           )
         })
 
+        it('works with a named location', () => {
+          const records = [
+            { path: '/home', component },
+            { path: '/redirect', name: 'redirect', redirect: { path: 'home' } },
+          ]
+          assertRedirect(
+            records,
+            {
+              name: 'redirect',
+            },
+            {
+              redirect: { path: 'home' },
+              normalizedLocation: {
+                path: '/redirect',
+                params: {},
+                name: 'redirect',
+                matched: [],
+              },
+            }
+          )
+        })
+
+        it('throws if relative location when redirecting', () => {
+          const records = [
+            { path: '/home', component },
+            { path: '/redirect', redirect: '/home' },
+          ]
+          expect(
+            assertErrorMatch(
+              { path: '/redirect', redirect: '/home' },
+              { params: {} },
+              { path: '/redirect', params: {}, matched: [], name: undefined }
+            )
+          ).toMatchInlineSnapshot(`
+            [Error: Cannot redirect using a relative location:
+            {
+              "params": {}
+            }
+            Use the function redirect and explicitely provide a name]
+          `)
+        })
+
         it('normalize a location when redirecting', () => {
           const redirect = to => ({ name: 'b', params: to.params })
           const records = [
index 923794b7e25783869323f6c798c78599e10869a8..f7038b492c0752c66d12231cb8a70d4f79d0edcb 100644 (file)
@@ -7,6 +7,21 @@ export class NoRouteMatchError extends Error {
   }
 }
 
+/**
+ * Error used when the matcher fails to resolve a location
+ */
+export class InvalidRouteMatch extends Error {
+  constructor(location: any) {
+    // TODO: improve the error to include currentLocation and use it for more cases
+    super(
+      `Cannot redirect using a relative location:\n${stringifyRoute(
+        location
+      )}\nUse the function redirect and explicitely provide a name`
+    )
+    Object.setPrototypeOf(this, new.target.prototype)
+  }
+}
+
 /**
  * Error used when rejecting a navigation because of a redirection. Contains
  * information about where we where trying to go and where we are going instead
@@ -30,5 +45,5 @@ export class RedirectError extends Error {
 function stringifyRoute(to: RouteLocation): string {
   if (typeof to === 'string') return to
   if ('path' in to) return to.path
-  return 'TODO'
+  return JSON.stringify(to, null, 2)
 }
index 3385f53a5526d34393a7c10fd3f82749bc2c48cc..46baa6a3beac3fcce4ce6376ae29a0047134f57a 100644 (file)
@@ -6,7 +6,7 @@ import {
   MatcherLocationNormalized,
   MatcherLocationRedirect,
 } from './types/index'
-import { NoRouteMatchError } from './errors'
+import { NoRouteMatchError, InvalidRouteMatch } from './errors'
 
 interface RouteMatcher {
   re: RegExp
@@ -86,12 +86,6 @@ export class RouterMatcher {
             params,
           },
         }
-        // if redirect is a function we do not have enough information, so we throw
-        // TODO: not use a throw
-        // throw new RedirectInRecord(typeof redirect === 'function' ? {
-        //   redirect,
-        //   route: { name: matcher.record.name, path: location.path, params, matched: [] }
-        // } : redirect)
       }
 
       // TODO: build up the array with children based on current location
@@ -111,7 +105,19 @@ export class RouterMatcher {
       matcher = this.matchers.find(m => m.record.name === location.name)
 
       if (!matcher) throw new NoRouteMatchError(currentLocation, location)
-      if ('redirect' in matcher.record) throw new Error('TODO')
+
+      if ('redirect' in matcher.record) {
+        const { redirect } = matcher.record
+        return {
+          redirect,
+          normalizedLocation: {
+            name: matcher.record.name,
+            path: matcher.resolve(location.params),
+            matched: [],
+            params: location.params || {}, // TODO: normalize params
+          },
+        }
+      }
 
       // TODO: build up the array with children based on current location
       const matched = [matcher.record]
@@ -136,7 +142,10 @@ export class RouterMatcher {
     }
 
     if (!matcher) throw new NoRouteMatchError(currentLocation, location)
-    if ('redirect' in matcher.record) throw new Error('TODO')
+
+    // this should never happen because it will mean that the user ended up in a route
+    // that redirects but ended up not redirecting
+    if ('redirect' in matcher.record) throw new InvalidRouteMatch(location)
 
     // TODO: build up the array with children based on current location
     const matched = [matcher.record]