]> git.ipfire.org Git - thirdparty/vuejs/router.git/commitdiff
fix: ignore order of keys in query and params
authorEduardo San Martin Morote <posva13@gmail.com>
Tue, 7 Apr 2020 13:32:08 +0000 (15:32 +0200)
committerEduardo San Martin Morote <posva13@gmail.com>
Tue, 7 Apr 2020 13:32:08 +0000 (15:32 +0200)
__tests__/location.spec.ts
src/utils/index.ts

index 845e3959f0707c4d57d510f4ddb7d4f01a563bbc..e5a9f93e6999d10a606a3cb886310c86150eee01 100644 (file)
@@ -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)
+  })
+})
index 17969f45e1b5cbaf79d1655526c98fd08ef48589..932bafd15904df76c2607594ff4b2c0290ae83a4 100644 (file)
@@ -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<T>(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
 }