]> git.ipfire.org Git - thirdparty/vuejs/router.git/commitdiff
feat(matcher): remove aliases alongside the original record
authorEduardo San Martin Morote <posva13@gmail.com>
Sat, 14 Mar 2020 22:40:19 +0000 (23:40 +0100)
committerEduardo San Martin Morote <posva13@gmail.com>
Sat, 14 Mar 2020 22:40:19 +0000 (23:40 +0100)
__tests__/matcher/addingRemoving.spec.ts
src/matcher/index.ts
src/matcher/path-matcher.ts

index b377d35a941368963f631db6a613de8105203a37..d6341cf14499df89e2fb17cf6db4b50a3ce0eb34 100644 (file)
@@ -60,8 +60,70 @@ describe('normalizeRouteRecord', () => {
       })
     })
 
-    it.todo('remove aliases')
-    it.todo('remove aliases children')
+    it('remove aliases', () => {
+      const matcher = createRouterMatcher([], {})
+      const remove = matcher.addRoute({
+        path: '/',
+        component,
+        name: 'home',
+        alias: ['/home', '/start'],
+      })
+      remove()
+      expect(matcher.resolve({ path: '/' }, currentLocation)).toMatchObject({
+        path: '/',
+        name: undefined,
+        matched: [],
+      })
+      expect(matcher.resolve({ path: '/home' }, currentLocation)).toMatchObject(
+        {
+          path: '/home',
+          name: undefined,
+          matched: [],
+        }
+      )
+      expect(
+        matcher.resolve({ path: '/start' }, currentLocation)
+      ).toMatchObject({
+        path: '/start',
+        name: undefined,
+        matched: [],
+      })
+    })
+
+    it('remove aliases children', () => {
+      const matcher = createRouterMatcher([], {})
+      const remove = matcher.addRoute({
+        path: '/',
+        component,
+        name: 'home',
+        alias: ['/home', '/start'],
+        children: [
+          {
+            path: 'one',
+            alias: ['o, o2'],
+            component,
+            children: [{ path: 'two', alias: ['t', 't2'], component }],
+          },
+        ],
+      })
+      remove()
+      ;[
+        '/',
+        '/start',
+        '/home',
+        '/one/two',
+        '/start/one/two',
+        '/home/o/two',
+        '/home/one/t2',
+        '/o2/t',
+      ].forEach(path => {
+        expect(matcher.resolve({ path }, currentLocation)).toMatchObject({
+          path,
+          name: undefined,
+          matched: [],
+        })
+      })
+    })
 
     it('remove children when removing the parent', () => {
       const matcher = createRouterMatcher([], {})
@@ -176,7 +238,95 @@ describe('normalizeRouteRecord', () => {
     expect(matcher.getRecordMatcher('child')).toBe(undefined)
   })
 
-  it.todo('removes alias by name')
+  it('removes alias (and original) by name', () => {
+    const matcher = createRouterMatcher([], {})
+    matcher.addRoute({
+      path: '/',
+      alias: '/start',
+      component,
+      name: 'home',
+    })
+
+    matcher.removeRoute('home')
+
+    expect(matcher.resolve({ path: '/start' }, currentLocation)).toMatchObject({
+      name: undefined,
+      matched: [],
+    })
+  })
+
+  it('removes all children alias when removing parent by name', () => {
+    const matcher = createRouterMatcher([], {})
+    matcher.addRoute({
+      path: '/',
+      alias: ['/start', '/home'],
+      component,
+      name: 'home',
+      children: [
+        {
+          path: 'one',
+          alias: ['o', 'o2'],
+          component,
+          children: [{ path: 'two', alias: ['t', 't2'], component }],
+        },
+      ],
+    })
+
+    matcher.removeRoute('home')
+    ;[
+      '/',
+      '/start',
+      '/home',
+      '/one/two',
+      '/start/one/two',
+      '/home/o/two',
+      '/home/one/t2',
+      '/o2/t',
+    ].forEach(path => {
+      expect(matcher.resolve({ path }, currentLocation)).toMatchObject({
+        path,
+        name: undefined,
+        matched: [],
+      })
+    })
+  })
+
+  it('removes children alias (and original) by name', () => {
+    const matcher = createRouterMatcher([], {})
+    matcher.addRoute({
+      path: '/',
+      alias: '/start',
+      component,
+      name: 'home',
+      children: [{ path: 'about', alias: 'two', name: 'child', component }],
+    })
+
+    matcher.removeRoute('child')
+
+    expect(matcher.resolve({ path: '/about' }, currentLocation)).toMatchObject({
+      name: undefined,
+      matched: [],
+    })
+
+    expect(matcher.resolve({ path: '/two' }, currentLocation)).toMatchObject({
+      name: undefined,
+      matched: [],
+    })
 
-  it.todo('removes children alias by name')
+    expect(
+      matcher.resolve({ path: '/start/about' }, currentLocation)
+    ).toMatchObject({
+      name: undefined,
+      matched: [],
+    })
+
+    expect(
+      matcher.resolve({ path: '/start/two' }, currentLocation)
+    ).toMatchObject({
+      name: undefined,
+      matched: [],
+    })
+
+    expect(matcher.getRecordMatcher('child')).toBe(undefined)
+  })
 })
index 621eb226c84a7626634eb2bdbb5096382d1c8aab..1246aa92663044e20addc499ed34a263750e4490 100644 (file)
@@ -13,6 +13,8 @@ import {
   PathParserOptions,
 } from './path-parser-ranker'
 
+let noop = () => {}
+
 interface RouterMatcher {
   addRoute: (
     record: RouteRecord,
@@ -72,6 +74,7 @@ export function createRouterMatcher(
     }
 
     let matcher: RouteRecordMatcher
+    let originalMatcher: RouteRecordMatcher | undefined
 
     for (const normalizedRecord of normalizedRecords) {
       let { path } = normalizedRecord
@@ -89,6 +92,16 @@ export function createRouterMatcher(
       // create the object before hand so it can be passed to children
       matcher = createRouteRecordMatcher(normalizedRecord, parent, options)
 
+      // if we are an alias we must tell the original record that we exist
+      // so we can be removed
+      if (originalRecord) {
+        originalRecord.alias.push(matcher)
+      } else {
+        // otherwise, the first record is the original and others are aliases
+        originalMatcher = originalMatcher || matcher
+        if (originalMatcher !== matcher) originalMatcher.alias.push(matcher)
+      }
+
       let children = mainNormalizedRecord.children
       for (let i = 0; i < children.length; i++) {
         addRoute(
@@ -105,20 +118,22 @@ export function createRouterMatcher(
       insertMatcher(matcher)
     }
 
-    return () => {
-      // since other matchers are aliases, they should should be removed by any of the matchers
-      removeRoute(matcher)
-    }
+    return originalMatcher
+      ? () => {
+          // since other matchers are aliases, they should be removed by the original matcher
+          removeRoute(originalMatcher!)
+        }
+      : noop
   }
 
   function removeRoute(matcherRef: string | RouteRecordMatcher) {
-    // TODO: remove aliases (needs to keep them in the RouteRecordMatcher first)
     if (typeof matcherRef === 'string') {
       const matcher = matcherMap.get(matcherRef)
       if (matcher) {
         matcherMap.delete(matcherRef)
         matchers.splice(matchers.indexOf(matcher), 1)
         matcher.children.forEach(removeRoute)
+        matcher.alias.forEach(removeRoute)
       }
     } else {
       let index = matchers.indexOf(matcherRef)
@@ -126,6 +141,7 @@ export function createRouterMatcher(
         matchers.splice(index, 1)
         if (matcherRef.record.name) matcherMap.delete(matcherRef.record.name)
         matcherRef.children.forEach(removeRoute)
+        matcherRef.alias.forEach(removeRoute)
       }
     }
   }
index 0d315e289da3f00822d83f2374a238faf2af22d6..34c5f47ac43ac28a01b4a474654dae2544207c4d 100644 (file)
@@ -10,6 +10,8 @@ export interface RouteRecordMatcher extends PathParser {
   record: RouteRecordNormalized
   parent: RouteRecordMatcher | undefined
   children: RouteRecordMatcher[]
+  // aliases that must be removed when removing this record
+  alias: RouteRecordMatcher[]
 }
 
 export function createRouteRecordMatcher(
@@ -25,6 +27,7 @@ export function createRouteRecordMatcher(
     parent,
     // these needs to be populated by the parent
     children: [],
+    alias: [],
   }
 
   if (parent) {