Skip to content

Commit

Permalink
feat: throw if parent and child routes have the same name (#2267)
Browse files Browse the repository at this point in the history
Co-authored-by: Eduardo San Martin Morote <[email protected]>
  • Loading branch information
skirtles-code and posva authored Oct 29, 2024
1 parent ab62098 commit 8c73877
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 1 deletion.
46 changes: 46 additions & 0 deletions packages/router/__tests__/matcher/addingRemoving.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,52 @@ describe('Matcher: adding and removing records', () => {
})
})

it('throws if a parent and child have the same name', () => {
expect(() => {
createRouterMatcher(
[
{
path: '/',
component,
name: 'home',
children: [{ path: '/home', component, name: 'home' }],
},
],
{}
)
}).toThrowError(
'A route named "home" has been added as a child of a route with the same name'
)
})

it('throws if an ancestor and descendant have the same name', () => {
const name = Symbol('home')
const matcher = createRouterMatcher(
[
{
path: '/',
name,
children: [
{
path: 'home',
name: 'other',
component,
},
],
},
],
{}
)

const parent = matcher.getRecordMatcher('other')

expect(() => {
matcher.addRoute({ path: '', component, name }, parent)
}).toThrowError(
'A route named "Symbol(home)" has been added as a descendant of a route with the same name'
)
})

it('adds empty paths as children', () => {
const matcher = createRouterMatcher([], {})
matcher.addRoute({ path: '/', component, name: 'parent' })
Expand Down
21 changes: 20 additions & 1 deletion packages/router/src/matcher/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,8 +159,12 @@ export function createRouterMatcher(

// remove the route if named and only for the top record (avoid in nested calls)
// this works because the original record is the first one
if (isRootAdd && record.name && !isAliasRecord(matcher))
if (isRootAdd && record.name && !isAliasRecord(matcher)) {
if (__DEV__) {
checkSameNameAsAncestor(record, parent)
}
removeRoute(record.name)
}
}

// Avoid adding a record that doesn't display anything. This allows passing through records without a component to
Expand Down Expand Up @@ -529,6 +533,21 @@ function checkChildMissingNameWithEmptyPath(
}
}

function checkSameNameAsAncestor(
record: RouteRecordRaw,
parent?: RouteRecordMatcher
) {
for (let ancestor = parent; ancestor; ancestor = ancestor.parent) {
if (ancestor.record.name === record.name) {
throw new Error(
`A route named "${String(record.name)}" has been added as a ${
parent === ancestor ? 'child' : 'descendant'
} of a route with the same name. Route names must be unique and a nested route cannot use the same name as an ancestor.`
)
}
}
}

function checkMissingParamsInAbsolutePath(
record: RouteRecordMatcher,
parent: RouteRecordMatcher
Expand Down

0 comments on commit 8c73877

Please sign in to comment.