Skip to content

Commit

Permalink
Merge pull request #712 from tighten/route-current-nested-params
Browse files Browse the repository at this point in the history
Fix `route().current()` with nested/object query params
  • Loading branch information
bakerkretzmar authored Feb 20, 2024
2 parents 7963d8d + 4781166 commit 4995308
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 1 deletion.
21 changes: 20 additions & 1 deletion src/js/Router.js
Original file line number Diff line number Diff line change
Expand Up @@ -137,9 +137,28 @@ export default class Router extends String {
)
return true;

const isSubset = (subset, full) => {
return Object.entries(subset).every(([key, value]) => {
if (Array.isArray(value) && Array.isArray(full[key])) {
return value.every((v) => full[key].includes(v));
}

if (
typeof value === 'object' &&
typeof full[key] === 'object' &&
value !== null &&
full[key] !== null
) {
return isSubset(value, full[key]);
}

return full[key] == value;
});
};

// Check that all passed parameters match their values in the current window URL
// Use weak equality because all values in the current window URL will be strings
return Object.entries(params).every(([key, value]) => routeParams[key] == value);
return isSubset(params, routeParams);
}

/**
Expand Down
69 changes: 69 additions & 0 deletions tests/js/route.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1233,6 +1233,75 @@ describe('current()', () => {
expect(route().current('events.venues.show', { id: 12, user: 'Matt' })).toBe(false);
});

test('can check the current route with array and object query parameters', () => {
global.window.location.pathname = '/events/1/venues/2';
global.window.location.search =
'?filter[year]=2024&filter[month]=Jan&filter[month]=Feb&tags[0]=music&tags[1]=dance&genres[]=jazz&genres[]=folk';

expect(
route().current('events.venues.show', {
filter: {
year: '2024',
},
}),
).toBe(true);
// Weird, but technically correct since this isn't checking for an exact match, just 'overlap'
expect(
route().current('events.venues.show', {
filter: {},
}),
).toBe(true);
// Even weirder, but probably better than getting really picky about empty arrays vs. empty objects
expect(
route().current('events.venues.show', {
genres: {},
}),
).toBe(true);
expect(
route().current('events.venues.show', {
filter: {
year: '2024',
month: ['Jan'],
},
tags: ['dance', 'music'],
genres: ['folk'],
}),
).toBe(true);

expect(
route().current('events.venues.show', {
filter: {
year: '2025',
},
}),
).toBe(false);
expect(
route().current('events.venues.show', {
filter: {
year: null,
},
}),
).toBe(false);
expect(
route().current('events.venues.show', {
filter: {
year: '2024',
month: ['Mar'],
},
}),
).toBe(false);
expect(
route().current('events.venues.show', {
tags: [''],
}),
).toBe(false);
expect(
route().current('events.venues.show', {
genres: [null],
}),
).toBe(false);
});

test('can check the current route with Cyrillic characters', () => {
global.window.location.pathname = '/статистика';

Expand Down

0 comments on commit 4995308

Please sign in to comment.