Skip to content

Commit 91aa0ac

Browse files
authored
Fix duplicated searchParams for pagination API (#1229)
1 parent 7dbb9ee commit 91aa0ac

File tree

3 files changed

+65
-4
lines changed

3 files changed

+65
-4
lines changed

readme.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1178,7 +1178,7 @@ Options are deeply merged to a new object. The value of each key is determined a
11781178
- If the parent property is a plain `object`, the parent value is deeply cloned.
11791179
- Otherwise, `undefined` is used.
11801180
- If the parent value is an instance of `URLSearchParams`:
1181-
- If the new value is a `string`, an `object` or an instance of `URLSearchParams`, a new `URLSearchParams` instance is created. The values are merged using [`urlSearchParams.append(key, value)`](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams/append).
1181+
- If the new value is a `string`, an `object` or an instance of `URLSearchParams`, a new `URLSearchParams` instance is created. The values are merged using [`urlSearchParams.append(key, value)`](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams/append). The keys defined in the new value override the keys defined in the parent value.
11821182
- Otherwise, the only available value is `undefined`.
11831183
- If the new property is a plain `object`:
11841184
- If the parent property is a plain `object` too, both values are merged recursively into a new `object`.

source/core/index.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -656,12 +656,17 @@ export default class Request extends Duplex implements RequestEvents<Request> {
656656
validateSearchParameters(options.searchParams);
657657
}
658658

659-
options.searchParams = new URLSearchParams(options.searchParams as Record<string, string>);
659+
const searchParameters = new URLSearchParams(options.searchParams as Record<string, string>);
660660

661661
// `normalizeArguments()` is also used to merge options
662662
defaults?.searchParams?.forEach((value, key) => {
663-
(options!.searchParams as URLSearchParams).append(key, value);
663+
// Only use default if one isn't already defined
664+
if (!searchParameters.has(key)) {
665+
searchParameters.append(key, value);
666+
}
664667
});
668+
669+
options.searchParams = searchParameters;
665670
}
666671
}
667672

test/pagination.ts

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -531,7 +531,7 @@ test('next url in json response', withServer, async (t, server, got) => {
531531
]);
532532
});
533533

534-
test.failing('pagination using searchParams', withServer, async (t, server, got) => {
534+
test('pagination using searchParams', withServer, async (t, server, got) => {
535535
server.get('/', (request, response) => {
536536
const parameters = new URLSearchParams(request.url.slice(2));
537537
const page = Number(parameters.get('page') ?? 0);
@@ -580,3 +580,59 @@ test.failing('pagination using searchParams', withServer, async (t, server, got)
580580
'/?page=3'
581581
]);
582582
});
583+
584+
test('pagination using extended searchParams', withServer, async (t, server, got) => {
585+
server.get('/', (request, response) => {
586+
const parameters = new URLSearchParams(request.url.slice(2));
587+
const page = Number(parameters.get('page') ?? 0);
588+
589+
response.end(JSON.stringify({
590+
currentUrl: request.url,
591+
next: page < 3
592+
}));
593+
});
594+
595+
interface Page {
596+
currentUrl: string;
597+
next?: string;
598+
}
599+
600+
const client = got.extend({
601+
searchParams: {
602+
limit: 10
603+
}
604+
});
605+
606+
const all = await client.paginate.all('', {
607+
searchParams: {
608+
page: 0
609+
},
610+
responseType: 'json',
611+
pagination: {
612+
transform: (response: Response<Page>) => {
613+
return [response.body.currentUrl];
614+
},
615+
paginate: (response: Response<Page>) => {
616+
const {next} = response.body;
617+
const previousPage = Number(response.request.options.searchParams!.get('page'));
618+
619+
if (!next) {
620+
return false;
621+
}
622+
623+
return {
624+
searchParams: {
625+
page: previousPage + 1
626+
}
627+
};
628+
}
629+
}
630+
});
631+
632+
t.deepEqual(all, [
633+
'/?page=0&limit=10',
634+
'/?page=1&limit=10',
635+
'/?page=2&limit=10',
636+
'/?page=3&limit=10'
637+
]);
638+
});

0 commit comments

Comments
 (0)