Skip to content

Commit

Permalink
Handle empty search string and badly formed search strings
Browse files Browse the repository at this point in the history
  • Loading branch information
apata committed Jan 9, 2025
1 parent 8495f60 commit 7df16a1
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 4 deletions.
24 changes: 24 additions & 0 deletions assets/js/dashboard/util/url-search-params.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,32 @@ describe(`${serializeSimpleSearchEntry.name} and ${parseSimpleSearchEntry.name}`
)
})

describe(`${parseSearch.name}`, () => {
it.each([
['?', {}, ''],
['?=&&', {}, ''],
['?=undefined', {}, ''],
['?foo=', { foo: '' }, '?foo='],
['??foo', { '?foo': '' }, '?%3Ffoo='],
[
'?f=is,visit:page,/any/page&f',
{ filters: [['is', 'visit:page', ['/any/page']]] },
'?f=is,visit:page,/any/page'
]
])(
'for search string %s, returns search record %p, which in turn stringifies to %s',
(searchString, expectedSearchRecord, expectedRestringifiedResult) => {
expect(parseSearch(searchString)).toEqual(expectedSearchRecord)
expect(stringifySearch(expectedSearchRecord)).toEqual(
expectedRestringifiedResult
)
}
)
})

describe(`${stringifySearch.name}`, () => {
it.each([
[{}, ''],
[
{
filters: [['is', 'props:browser_language', ['en-US']]]
Expand Down
23 changes: 19 additions & 4 deletions assets/js/dashboard/util/url-search-params.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,27 @@ export function stringifySearch(
return `?${serializedFilters.concat(serializedLabels).concat(definedSearchEntries).join('&')}`
}

export function normalizeSearchString(searchString: string): string {
return searchString.startsWith('?') ? searchString.slice(1) : searchString
}

export function parseSearch(searchString: string): Record<string, unknown> {
const searchRecord: Record<string, string | boolean> = {}
const filters: Filter[] = []
const labels: FilterClauseLabels = {}

for (const param of searchString.startsWith('?')
? searchString.slice(1).split('&')
: searchString.split('&')) {
const [key, rawValue] = param.split('=')
const normalizedSearchString = normalizeSearchString(searchString)

if (!normalizedSearchString.length) {
return searchRecord
}

const meaningfulParams = normalizedSearchString
.split('&')
.filter((i) => i.length > 0)

for (const param of meaningfulParams) {
const [key, rawValue = ''] = param.split('=')
switch (key) {
case FILTER_URL_PARAM_NAME: {
const filter = parseFilter(rawValue)
Expand All @@ -55,6 +67,9 @@ export function parseSearch(searchString: string): Record<string, unknown> {
}
break
}
case '': {
break
}
default: {
const parsedValue = parseSimpleSearchEntry(rawValue)
if (parsedValue !== null) {
Expand Down

0 comments on commit 7df16a1

Please sign in to comment.