Skip to content

Commit

Permalink
fix(router): prevent duplicated navigation on aliases
Browse files Browse the repository at this point in the history
  • Loading branch information
posva committed Mar 14, 2020
1 parent 35a0bc0 commit e825586
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 11 deletions.
69 changes: 69 additions & 0 deletions __tests__/router.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,26 @@ const routes: RouteRecord[] = [
hash: to.hash + '-2',
}),
},
{
path: '/basic',
alias: '/basic-alias',
component: components.Foo,
},
{
path: '/aliases',
alias: ['/aliases1', '/aliases2'],
component: components.Nested,
children: [
{
path: 'one',
alias: ['o', 'o2'],
component: components.Foo,
children: [
{ path: 'two', alias: ['t', 't2'], component: components.Bar },
],
},
],
},
]

async function newRouter({ history }: { history?: RouterHistory } = {}) {
Expand Down Expand Up @@ -111,6 +131,55 @@ describe('Router', () => {
)
})

// FIXME:
it.skip('navigates if the location does not exist', async () => {
const { router } = await newRouter()
const spy = jest.fn((to, from, next) => next())
router.beforeEach(spy)
await router.push('/idontexist')
spy.mockReset()
await router.push('/me-neither')
expect(spy).not.toHaveBeenCalled()
})

describe('alias', () => {
it('does not navigate to alias if already on original record', async () => {
const { router } = await newRouter()
const spy = jest.fn((to, from, next) => next())
router.beforeEach(spy)
await router.push('/basic')
spy.mockReset()
await router.push('/basic-alias')
expect(spy).not.toHaveBeenCalled()
})

it('does not navigate to alias with children if already on original record', async () => {
const { router } = await newRouter()
const spy = jest.fn((to, from, next) => next())
router.beforeEach(spy)
await router.push('/aliases')
spy.mockReset()
await router.push('/aliases1')
expect(spy).not.toHaveBeenCalled()
await router.push('/aliases2')
expect(spy).not.toHaveBeenCalled()
})

it('does not navigate to child alias if already on original record', async () => {
const { router } = await newRouter()
const spy = jest.fn((to, from, next) => next())
router.beforeEach(spy)
await router.push('/aliases/one')
spy.mockReset()
await router.push('/aliases1/one')
expect(spy).not.toHaveBeenCalled()
await router.push('/aliases2/one')
expect(spy).not.toHaveBeenCalled()
await router.push('/aliases2/o')
expect(spy).not.toHaveBeenCalled()
})
})

describe('navigation', () => {
async function checkNavigationCancelledOnPush(
target?: RouteLocation | false | ((vm: any) => void)
Expand Down
37 changes: 26 additions & 11 deletions src/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ import {
import {
extractComponentsGuards,
guardToPromiseFn,
isSameLocationObject,
applyToParams,
isSameRouteRecord,
isSameLocationObject,
} from './utils'
import { useCallbacks } from './utils/callbacks'
import { encodeParam, decode } from './utils/encoding'
Expand Down Expand Up @@ -199,7 +199,7 @@ export function createRouter({
const force: boolean | undefined = to.force

// TODO: should we throw an error as the navigation was aborted
if (!force && isSameLocation(from, toLocation)) return from
if (!force && isSameRouteLocation(from, toLocation)) return from

toLocation.redirectedFrom = redirectedFrom

Expand Down Expand Up @@ -543,16 +543,31 @@ function extractChangingRecords(
return [leavingRecords, updatingRecords, enteringRecords]
}

function isSameLocation(
a: Immutable<RouteLocationNormalized>,
b: Immutable<RouteLocationNormalized>
// function isSameLocation(
// a: Immutable<RouteLocationNormalized>,
// b: Immutable<RouteLocationNormalized>
// ): boolean {
// return (
// a.name === b.name &&
// a.path === b.path &&
// a.hash === b.hash &&
// isSameLocationObject(a.query, b.query) &&
// a.matched.length === b.matched.length &&
// a.matched.every((record, i) => isSameRouteRecord(record, b.matched[i]))
// )
// }

function isSameRouteLocation(
a: RouteLocationNormalized,
b: RouteLocationNormalized
): boolean {
let aLastIndex = a.matched.length - 1
let bLastIndex = b.matched.length - 1

return (
a.name === b.name &&
a.path === b.path &&
a.hash === b.hash &&
isSameLocationObject(a.query, b.query) &&
a.matched.length === b.matched.length &&
a.matched.every((record, i) => isSameRouteRecord(record, b.matched[i]))
aLastIndex > -1 &&
aLastIndex === bLastIndex &&
isSameRouteRecord(a.matched[aLastIndex], b.matched[bLastIndex]) &&
isSameLocationObject(a.params, b.params)
)
}

0 comments on commit e825586

Please sign in to comment.