]> git.ipfire.org Git - thirdparty/vuejs/router.git/commitdiff
fix(types): ajust types in Matcher
authorEduardo San Martin Morote <posva13@gmail.com>
Mon, 1 Jul 2019 15:49:14 +0000 (17:49 +0200)
committerEduardo San Martin Morote <posva13@gmail.com>
Mon, 1 Jul 2019 15:49:14 +0000 (17:49 +0200)
__tests__/extractComponentsGuards.spec.js
__tests__/matcher.spec.js
__tests__/router-view.spec.js
__tests__/utils.ts
src/types/index.ts
src/utils/index.ts

index 3b1663e6e244732863730039321faa5134514103..9690e7431305218b2cb5649877647578f9f502da 100644 (file)
@@ -1,10 +1,9 @@
 // @ts-check
 require('./helper')
 const expect = require('expect')
-const { normalizeRecord } = require('../src/matcher')
 const { extractComponentsGuards } = require('../src/utils')
 const { START_LOCATION_NORMALIZED } = require('../src/types')
-const { components } = require('./utils')
+const { components, normalizeRouteRecord } = require('./utils')
 
 /** @typedef {import('../src/types').RouteRecord} RouteRecord */
 /** @typedef {import('../src/types').MatchedRouteRecord} MatchedRouteRecord */
@@ -34,7 +33,7 @@ const SingleGuardNamed = {
 
 /**
  *
- * @param {MatchedRouteRecord} record
+ * @param {Exclude<RouteRecord, { redirect: any}>} record
  * @returns {MatchedRouteRecord}
  */
 function makeAsync(record) {
@@ -49,11 +48,15 @@ function makeAsync(record) {
     )
     return copy
   } else {
-    if (typeof record.component === 'function') return { ...record }
-    // @ts-ignore
+    const { component, ...copy } = record
+    if (typeof component === 'function')
+      return { ...copy, components: { default: component } }
+
     return {
-      ...record,
-      component: () => Promise.resolve(record.component),
+      ...copy,
+      components: {
+        default: () => Promise.resolve(component),
+      },
     }
   }
 }
@@ -67,14 +70,14 @@ beforeEach(() => {
 
 /**
  *
- * @param {Exclude<RouteRecord, RouteRecordRedirect>[]} components
+ * @param {Exclude<RouteRecord, { redirect: any }>[]} components
+ * @param {number} n
  */
 async function checkGuards(components, n) {
   beforeRouteEnter.mockClear()
-  const ncomps = components.map(normalizeRecord)
   const guards = await extractComponentsGuards(
     // type is fine as we excluded RouteRecordRedirect in components argument
-    components.map(normalizeRecord),
+    components.map(normalizeRouteRecord),
     'beforeRouteEnter',
     to,
     from
index d33afbc3b3044b7fe712b7dadab89a66921caad7..d7102ffa2e1c702a0eec580f4a2abeb217d427fd 100644 (file)
@@ -3,10 +3,12 @@ require('./helper')
 const expect = require('expect')
 const { RouterMatcher } = require('../src/matcher')
 const { START_LOCATION_NORMALIZED } = require('../src/types')
+const { normalizeRouteRecord } = require('./utils')
 
 const component = null
 
 /** @typedef {import('../src/types').RouteRecord} RouteRecord */
+/** @typedef {import('../src/types').MatchedRouteRecord} MatchedRouteRecord */
 /** @typedef {import('../src/types').MatcherLocation} MatcherLocation */
 /** @typedef {import('../src/types').MatcherLocationRedirect} MatcherLocationRedirect */
 /** @typedef {import('../src/types').MatcherLocationNormalized} MatcherLocationNormalized */
@@ -171,7 +173,12 @@ describe('Router Matcher', () => {
           record,
           {},
           { name: 'Home', path: '/home' },
-          { name: 'Home', params: {}, path: '/home', matched: [record] }
+          {
+            name: 'Home',
+            params: {},
+            path: '/home',
+            matched: [normalizeRouteRecord(record)],
+          }
         )
       })
 
@@ -185,7 +192,7 @@ describe('Router Matcher', () => {
             path: '/users/ed/m/user',
             name: undefined,
             params: { id: 'ed', role: 'user' },
-            matched: [record],
+            matched: [record].map(normalizeRouteRecord),
           }
         )
       })
@@ -227,7 +234,7 @@ describe('Router Matcher', () => {
             path: '/users/ed/m/user',
             name: 'UserEdit',
             params: { id: 'ed', role: 'user' },
-            matched: [record],
+            matched: [record].map(normalizeRouteRecord),
           }
         )
       })
@@ -246,7 +253,7 @@ describe('Router Matcher', () => {
             path: '/users/ed/m/user',
             name: undefined,
             params: { id: 'ed', role: 'user' },
-            matched: [record],
+            matched: [record].map(normalizeRouteRecord),
           }
         )
       })
@@ -445,7 +452,7 @@ describe('Router Matcher', () => {
           name: 'home',
           params: {},
           path: '/',
-          matched: [record],
+          matched: [record].map(normalizeRouteRecord),
         }
         // the property should be non enumerable
         Object.defineProperty(start, 'matched', { enumerable: false })
@@ -494,7 +501,10 @@ describe('Router Matcher', () => {
             name: 'child-b',
             path: '/foo/b',
             params: {},
-            matched: [Foo, { ...ChildB, path: `${Foo.path}/${ChildB.path}` }],
+            matched: [
+              Foo,
+              { ...ChildB, path: `${Foo.path}/${ChildB.path}` },
+            ].map(normalizeRouteRecord),
           }
         )
       })
@@ -514,7 +524,9 @@ describe('Router Matcher', () => {
             name: 'nested',
             path: '/foo',
             params: {},
-            matched: [Foo, { ...Nested, path: `${Foo.path}` }],
+            matched: [Foo, { ...Nested, path: `${Foo.path}` }].map(
+              normalizeRouteRecord
+            ),
           }
         )
       })
@@ -544,7 +556,7 @@ describe('Router Matcher', () => {
               Foo,
               { ...Nested, path: `${Foo.path}` },
               { ...NestedNested, path: `${Foo.path}` },
-            ],
+            ].map(normalizeRouteRecord),
           }
         )
       })
@@ -570,7 +582,7 @@ describe('Router Matcher', () => {
                 ...NestedChildA,
                 path: `${Foo.path}/${Nested.path}/${NestedChildA.path}`,
               },
-            ],
+            ].map(normalizeRouteRecord),
           }
         )
       })
@@ -596,7 +608,7 @@ describe('Router Matcher', () => {
                 ...NestedChildA,
                 path: `${Foo.path}/${Nested.path}/${NestedChildA.path}`,
               },
-            ],
+            ].map(normalizeRouteRecord),
           }
         )
       })
@@ -622,7 +634,7 @@ describe('Router Matcher', () => {
                 ...NestedChildA,
                 path: `${Foo.path}/${Nested.path}/${NestedChildA.path}`,
               },
-            ],
+            ].map(normalizeRouteRecord),
           },
           {
             name: 'nested-child-a',
@@ -657,7 +669,7 @@ describe('Router Matcher', () => {
                 ...NestedChildWithParam,
                 path: `${Foo.path}/${NestedWithParam.path}/${NestedChildWithParam.path}`,
               },
-            ],
+            ].map(normalizeRouteRecord),
           }
         )
       })
@@ -686,7 +698,7 @@ describe('Router Matcher', () => {
                 ...NestedChildWithParam,
                 path: `${Foo.path}/${NestedWithParam.path}/${NestedChildWithParam.path}`,
               },
-            ],
+            ].map(normalizeRouteRecord),
           }
         )
       })
index 3b28aed35760dbb316ca7d0f2eeb3cf37c634038..188a9a756226de04476e44eb178c9092e5b0ee21 100644 (file)
@@ -19,7 +19,7 @@ const routes = {
     query: {},
     params: {},
     hash: '',
-    meta: {},
+    // meta: {},
     matched: [{ components: { default: components.Home }, path: '/' }],
   },
 }
@@ -30,12 +30,20 @@ describe('RouterView', () => {
   if (isMocha()) return
   const { mount } = require('@vue/test-utils')
 
-  it('displays current route component', async () => {
-    const wrapper = await mount(RouterView, {
-      mocks: {
-        $route: routes.root,
-      },
+  /**
+   *
+   * @param {RouteLocationNormalized} $route
+   */
+  function factory($route) {
+    // @ts-ignore
+    const wrapper = mount(RouterView, {
+      mocks: { $route },
     })
+    return wrapper
+  }
+
+  it('displays current route component', async () => {
+    const wrapper = factory(routes.root)
     expect(wrapper.html()).toMatchInlineSnapshot(`"<div>Home</div>"`)
   })
 })
index 6110a6ae5d28b52a8a57c1d5f316a97857b6457b..c3791dd16b5ce2149e3dc3795062e1cca5dd1ba9 100644 (file)
@@ -1,6 +1,5 @@
 import { JSDOM, ConstructorOptions } from 'jsdom'
-import { NavigationGuard } from '../src/types'
-import { Component } from 'vue'
+import { NavigationGuard, RouteRecord, MatchedRouteRecord } from '../src/types'
 
 export { HistoryMock } from './HistoryMock'
 
@@ -33,10 +32,10 @@ export const noGuard: NavigationGuard = (to, from, next) => {
   next()
 }
 
-export const components: Record<string, Component> = {
-  Home: { render: h => h('div', {}, 'Home') },
-  Foo: { render: h => h('div', {}, 'Foo') },
-  Bar: { render: h => h('div', {}, 'Bar') },
+export const components = {
+  Home: { render: (h: Function) => h('div', {}, 'Home') },
+  Foo: { render: (h: Function) => h('div', {}, 'Foo') },
+  Bar: { render: (h: Function) => h('div', {}, 'Bar') },
 }
 
 // allow using a .jest modifider to skip some tests on mocha
@@ -44,3 +43,21 @@ export const components: Record<string, Component> = {
 // adapt to mocha
 // @ts-ignore
 export const isMocha = () => typeof global.before === 'function'
+
+/**
+ * Copies and normalizes the record so it always contains an object of `components`
+ *
+ * @param record
+ * @returns a normalized copy
+ */
+export function normalizeRouteRecord(
+  record: Exclude<RouteRecord, { redirect: any }>
+): MatchedRouteRecord {
+  if ('components' in record) return { ...record }
+  const { component, ...rest } = record
+
+  return {
+    ...rest,
+    components: { default: component },
+  }
+}
index fd36a445a632a512b07096751367147fcafc2488..1f74f46e7bdc1f0163d08997b2ebe3eab2bd082c 100644 (file)
@@ -1,4 +1,7 @@
 import { HistoryQuery, RawHistoryQuery } from '../history/base'
+// import Vue, { ComponentOptions, AsyncComponent } from 'vue'
+
+// type Component = ComponentOptions<Vue> | typeof Vue | AsyncComponent
 
 export type Lazy<T> = () => Promise<T>
 
@@ -87,12 +90,14 @@ export interface RouteComponentInterface {
 }
 
 // TODO: have a real type with augmented properties
-// export type RouteComponent = TODO & RouteComponentInterface
-export type RouteComponent = {
+// export type RouteComponent = Component & RouteComponentInterface
+type Component = {
   template?: string
   render?: Function
 } & RouteComponentInterface
 
+export type RouteComponent = Component | Lazy<Component>
+
 // NOTE not sure the whole PropsTransformer thing can be usefull
 // since in callbacks we don't know where we are coming from
 // and I don't thin it's possible to filter out the route
@@ -112,12 +117,12 @@ export interface RouteRecordRedirect extends RouteRecordCommon {
 }
 
 interface RouteRecordSingleView extends RouteRecordCommon {
-  component: RouteComponent | Lazy<RouteComponent>
+  component: RouteComponent
   children?: RouteRecord[]
 }
 
 interface RouteRecordMultipleViews extends RouteRecordCommon {
-  components: Record<string, RouteComponent | Lazy<RouteComponent>>
+  components: Record<string, RouteComponent>
   // TODO: add tests
   children?: RouteRecord[]
 }
index 91aa3c50811e86e0b882635e573095b0fd7d9aa4..fa58b1119317a5c58d242f3aa0dd5b399f835e23 100644 (file)
@@ -16,6 +16,8 @@ export async function extractComponentsGuards(
       // TODO: cache async routes per record
       for (const name in record.components) {
         const component = record.components[name]
+        // TODO: handle Vue.extend views
+        // if ('options' in component) throw new Error('TODO')
         const resolvedComponent = await (typeof component === 'function'
           ? component()
           : component)