From 15a0da9e87a3eaa8b425eeb49072240fc8afb3fe Mon Sep 17 00:00:00 2001 From: Eduardo San Martin Morote Date: Thu, 12 May 2022 11:36:31 +0200 Subject: [PATCH] feat: warn against named parent routes (#1396) Co-authored-by: Eating-Eating <47847099+Eating-Eating@users.noreply.github.com> --- __tests__/matcher/addingRemoving.spec.ts | 100 +++++++++++++++++++++++ src/matcher/index.ts | 27 ++++++ 2 files changed, 127 insertions(+) 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