From: Eduardo San Martin Morote Date: Tue, 7 Apr 2020 13:32:08 +0000 (+0200) Subject: fix: ignore order of keys in query and params X-Git-Tag: v4.0.0-alpha.5~8 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=643bd15ceaf9d6314434b15b169171b599b58e1c;p=thirdparty%2Fvuejs%2Frouter.git fix: ignore order of keys in query and params --- diff --git a/__tests__/location.spec.ts b/__tests__/location.spec.ts index 845e3959..e5a9f93e 100644 --- a/__tests__/location.spec.ts +++ b/__tests__/location.spec.ts @@ -5,6 +5,7 @@ import { stringifyURL as originalStringifyURL, stripBase, } from '../src/utils/location' +import { isSameLocationObject } from '../src/utils' describe('parseURL', () => { let parseURL = originalParseURL.bind(null, parseQuery) @@ -160,3 +161,34 @@ describe('stripBase', () => { expect(stripBase('/base/foo', '/base')).toBe('/foo') }) }) + +describe('isSameLocationObject', () => { + it('compare simple values', () => { + expect(isSameLocationObject({ a: '2' }, { a: '2' })).toBe(true) + expect(isSameLocationObject({ a: '3' }, { a: '2' })).toBe(false) + // different order + expect(isSameLocationObject({ a: '2', b: '3' }, { b: '3', a: '2' })).toBe( + true + ) + expect(isSameLocationObject({ a: '3', b: '3' }, { b: '3', a: '2' })).toBe( + false + ) + }) + + it('compare array values', () => { + expect(isSameLocationObject({ a: ['2'] }, { a: ['2'] })).toBe(true) + expect(isSameLocationObject({ a: ['3'] }, { a: ['2'] })).toBe(false) + // different order + expect( + isSameLocationObject({ a: ['2'], b: ['3'] }, { b: ['3'], a: ['2'] }) + ).toBe(true) + expect( + isSameLocationObject({ a: ['3'], b: ['3'] }, { b: ['3'], a: ['2'] }) + ).toBe(false) + }) + + it('considers arrays of one item same as the item itself', () => { + expect(isSameLocationObject({ a: ['2'] }, { a: '2' })).toBe(true) + expect(isSameLocationObject({ a: ['3'] }, { a: '2' })).toBe(false) + }) +}) diff --git a/src/utils/index.ts b/src/utils/index.ts index 17969f45..932bafd1 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -3,6 +3,7 @@ import { RouteParams, RouteComponent, RouteLocationNormalizedLoaded, + RouteParamValue, } from '../types' import { guardToPromiseFn } from './guardToPromiseFn' import { RouteRecord, RouteRecordNormalized } from '../matcher/types' @@ -90,16 +91,10 @@ export function isSameLocationObject( a: RouteLocationNormalized['query' | 'params'], b: RouteLocationNormalized['query' | 'params'] ): boolean { - const aKeys = Object.keys(a) - const bKeys = Object.keys(b) - if (aKeys.length !== bKeys.length) return false - let i = 0 - let key: string - while (i < aKeys.length) { - key = aKeys[i] - if (key !== bKeys[i]) return false + if (Object.keys(a).length !== Object.keys(b).length) return false + + for (let key in a) { if (!isSameLocationObjectValue(a[key], b[key])) return false - i++ } return true @@ -109,17 +104,38 @@ function isSameLocationObjectValue( a: LocationQueryValue | LocationQueryValue[], b: LocationQueryValue | LocationQueryValue[] ): boolean -function isSameLocationObjectValue(a: RouteParams, b: RouteParams): boolean function isSameLocationObjectValue( - a: LocationQueryValue | LocationQueryValue[] | RouteParams, - b: LocationQueryValue | LocationQueryValue[] | RouteParams + a: RouteParamValue | RouteParamValue[], + b: RouteParamValue | RouteParamValue[] +): boolean +function isSameLocationObjectValue( + a: + | LocationQueryValue + | LocationQueryValue[] + | RouteParamValue + | RouteParamValue[], + b: + | LocationQueryValue + | LocationQueryValue[] + | RouteParamValue + | RouteParamValue[] ): boolean { - if (typeof a !== typeof b) return false - // both a and b are arrays - if (Array.isArray(a)) - return ( - a.length === (b as any[]).length && - a.every((value, i) => value === (b as LocationQueryValue[])[i]) - ) - return a === b + return Array.isArray(a) + ? isEquivalentArray(a, b) + : Array.isArray(b) + ? isEquivalentArray(b, a) + : a === b +} + +/** + * Check if two arrays are the same or if an array with one single entry is the + * same as another primitive value. Used to check query and parameters + * + * @param a array of values + * @param b array of values or a single value + */ +function isEquivalentArray(a: T[], b: T[] | T): boolean { + return Array.isArray(b) + ? a.length === b.length && a.every((value, i) => value === b[i]) + : a.length === 1 && a[0] === b }