diff --git a/__tests__/matcher/addingRemoving.spec.ts b/__tests__/matcher/addingRemoving.spec.ts index 4819ff2e1..336262105 100644 --- a/__tests__/matcher/addingRemoving.spec.ts +++ b/__tests__/matcher/addingRemoving.spec.ts @@ -441,5 +441,105 @@ describe('Matcher: adding and removing records', () => { ) expect('same param named').not.toHaveBeenWarned() }) + + it('warns if a named route has an empty non-named child route', () => { + createRouterMatcher( + [ + { + name: 'UserRoute', + path: '/user/:id', + component, + children: [{ path: '', component }], + }, + ], + {} + ) + expect('has a child without a name').toHaveBeenWarned() + }) + + it('no warn if both or just the child are named', () => { + createRouterMatcher( + [ + { + name: 'UserRoute', + path: '/user/:id', + component, + children: [{ path: '', name: 'UserHome', component }], + }, + { + path: '/', + component, + children: [{ path: '', name: 'child', component }], + }, + ], + {} + ) + expect('has a child without a name').not.toHaveBeenWarned() + }) + + it('warns if nested child is missing a name', () => { + createRouterMatcher( + [ + { + name: 'parent', + path: '/a', + component, + children: [ + { + path: 'b', + name: 'b', + component, + children: [{ path: '', component }], + }, + ], + }, + ], + {} + ) + expect('has a child without a name').toHaveBeenWarned() + }) + + it('warns if middle nested child is missing a name', () => { + createRouterMatcher( + [ + { + path: '/a', + component, + children: [ + { + path: '', + name: 'parent', + component, + children: [{ path: '', component }], + }, + ], + }, + ], + {} + ) + expect('has a child without a name').toHaveBeenWarned() + }) + + it('no warn if nested child is named', () => { + createRouterMatcher( + [ + { + name: 'parent', + path: '/a', + component, + children: [ + { + path: 'b', + name: 'b', + component, + children: [{ path: '', name: 'child', component }], + }, + ], + }, + ], + {} + ) + expect('has a child without a name').not.toHaveBeenWarned() + }) }) }) diff --git a/src/matcher/index.ts b/src/matcher/index.ts index 1756020e2..d8b2dfb81 100644 --- a/src/matcher/index.ts +++ b/src/matcher/index.ts @@ -79,6 +79,9 @@ export function createRouterMatcher( // used later on to remove by name const isRootAdd = !originalRecord const mainNormalizedRecord = normalizeRouteRecord(record) + if (__DEV__) { + checkChildMissingNameWithEmptyPath(mainNormalizedRecord, parent) + } // we might be the child of an alias mainNormalizedRecord.aliasOf = originalRecord && originalRecord.record const options: PathParserOptions = mergeOptions(globalOptions, record) @@ -452,6 +455,30 @@ function checkSameParams(a: RouteRecordMatcher, b: RouteRecordMatcher) { } } +/** + * A route with a name and a child with an empty path without a name should warn when adding the route + * + * @param mainNormalizedRecord - RouteRecordNormalized + * @param parent - RouteRecordMatcher + */ +function checkChildMissingNameWithEmptyPath( + mainNormalizedRecord: RouteRecordNormalized, + parent?: RouteRecordMatcher +) { + if ( + parent && + parent.record.name && + !mainNormalizedRecord.name && + !mainNormalizedRecord.path + ) { + warn( + `The route named "${String( + parent.record.name + )}" has a child without a name and an empty path. Using that name won't render the empty path child so you probably want to move the name to the child instead. If this is intentional, add a name to the child route to remove the warning.` + ) + } +} + function checkMissingParamsInAbsolutePath( record: RouteRecordMatcher, parent: RouteRecordMatcher