From: Eduardo San Martin Morote Date: Mon, 1 Jul 2019 15:49:14 +0000 (+0200) Subject: fix(types): ajust types in Matcher X-Git-Tag: v4.0.0-alpha.0~321 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=14966baa161d254775f42325c6462505ce9365bd;p=thirdparty%2Fvuejs%2Frouter.git fix(types): ajust types in Matcher --- diff --git a/__tests__/extractComponentsGuards.spec.js b/__tests__/extractComponentsGuards.spec.js index 3b1663e6..9690e743 100644 --- a/__tests__/extractComponentsGuards.spec.js +++ b/__tests__/extractComponentsGuards.spec.js @@ -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} 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[]} components + * @param {Exclude[]} 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 diff --git a/__tests__/matcher.spec.js b/__tests__/matcher.spec.js index d33afbc3..d7102ffa 100644 --- a/__tests__/matcher.spec.js +++ b/__tests__/matcher.spec.js @@ -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), } ) }) diff --git a/__tests__/router-view.spec.js b/__tests__/router-view.spec.js index 3b28aed3..188a9a75 100644 --- a/__tests__/router-view.spec.js +++ b/__tests__/router-view.spec.js @@ -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(`"
Home
"`) }) }) diff --git a/__tests__/utils.ts b/__tests__/utils.ts index 6110a6ae..c3791dd1 100644 --- a/__tests__/utils.ts +++ b/__tests__/utils.ts @@ -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 = { - 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 = { // 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 +): MatchedRouteRecord { + if ('components' in record) return { ...record } + const { component, ...rest } = record + + return { + ...rest, + components: { default: component }, + } +} diff --git a/src/types/index.ts b/src/types/index.ts index fd36a445..1f74f46e 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -1,4 +1,7 @@ import { HistoryQuery, RawHistoryQuery } from '../history/base' +// import Vue, { ComponentOptions, AsyncComponent } from 'vue' + +// type Component = ComponentOptions | typeof Vue | AsyncComponent export type Lazy = () => Promise @@ -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 + // 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 + component: RouteComponent children?: RouteRecord[] } interface RouteRecordMultipleViews extends RouteRecordCommon { - components: Record> + components: Record // TODO: add tests children?: RouteRecord[] } diff --git a/src/utils/index.ts b/src/utils/index.ts index 91aa3c50..fa58b111 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -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)