fix(router): properly compare array queryParams for equality (#37709) (#37860)

queryParams will be judged different if the arrays do not contain the same frequency of elements and the same otherwise.

PR Close #37860
This commit is contained in:
Ruben Schuckit 2020-06-30 17:08:32 -04:00 committed by Alex Rickabaugh
parent a5c30733cb
commit 1801d0c650
3 changed files with 23 additions and 4 deletions

View File

@ -39,7 +39,6 @@ function equalSegmentGroups(container: UrlSegmentGroup, containee: UrlSegmentGro
}
function containsQueryParams(container: Params, containee: Params): boolean {
// TODO: This does not handle array params correctly.
return Object.keys(containee).length <= Object.keys(container).length &&
Object.keys(containee).every(key => equalArraysOrString(container[key], containee[key]));
}

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {NgModuleFactory, ɵisObservable as isObservable, ɵisPromise as isPromise} from '@angular/core';
import {ɵisObservable as isObservable, ɵisPromise as isPromise} from '@angular/core';
import {from, Observable, of} from 'rxjs';
import {concatAll, last as lastValue, map} from 'rxjs/operators';
@ -45,8 +45,10 @@ export function shallowEqual(a: Params, b: Params): boolean {
*/
export function equalArraysOrString(a: string|string[], b: string|string[]) {
if (Array.isArray(a) && Array.isArray(b)) {
if (a.length != b.length) return false;
return a.every(aItem => b.indexOf(aItem) > -1);
if (a.length !== b.length) return false;
const aSorted = [...a].sort();
const bSorted = [...b].sort();
return aSorted.every((val, index) => bSorted[index] === val);
} else {
return a === b;
}

View File

@ -67,6 +67,24 @@ describe('UrlTree', () => {
expect(containsTree(t1, t2, true)).toBe(false);
});
it('should return false when queryParams are not the same', () => {
const t1 = serializer.parse('/one/two?test=4&test=4&test=2');
const t2 = serializer.parse('/one/two?test=4&test=3&test=2');
expect(containsTree(t1, t2, false)).toBe(false);
});
it('should return true when queryParams are the same in different order', () => {
const t1 = serializer.parse('/one/two?test=4&test=3&test=2');
const t2 = serializer.parse('/one/two?test=2&test=3&test=4');
expect(containsTree(t1, t2, false)).toBe(true);
});
it('should return true when queryParams are the same in different order', () => {
const t1 = serializer.parse('/one/two?test=4&test=4&test=1');
const t2 = serializer.parse('/one/two?test=1&test=4&test=4');
expect(containsTree(t1, t2, false)).toBe(true);
});
it('should return false when containee is missing queryParams', () => {
const t1 = serializer.parse('/one/two?page=5');
const t2 = serializer.parse('/one/two');