diff --git a/src/utils.url.ts b/src/utils.url.ts index 5a725353..610ed852 100644 --- a/src/utils.url.ts +++ b/src/utils.url.ts @@ -90,6 +90,7 @@ export function withQuery(input: string, query?: QueryObject): string { if (value === undefined) { searchParams.delete(key); } else if (Array.isArray(value)) { + searchParams.delete(key); for (const item of value) { searchParams.append(key, normalizeQueryValue(item)); } diff --git a/test/index.test.ts b/test/index.test.ts index 5ac20b07..e8b86e3a 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -344,6 +344,20 @@ describe("ofetch", () => { }); }); + it("replaces existing array query params instead of accumulating", async () => { + // When the URL already carries a value for a key and the query option + // supplies an array for that same key, the existing value should be + // replaced, not accumulated alongside the new ones. The /url/** endpoint + // echoes the raw path+search so we can inspect all repeated values. + const result = await $fetch(getURL("url/check?tag=old&other=1"), { + query: { tag: ["a", "b"] }, + }); + // "tag=old" must not appear; only "tag=a" and "tag=b" should be present + expect(result).toContain("tag=a"); + expect(result).toContain("tag=b"); + expect(result).not.toContain("tag=old"); + }); + it("deep merges defaultOptions", async () => { const _customFetch = $fetch.create({ query: {