Vault: handle empty delete responses (#913)

Co-authored-by: Viet Tran <viettranx@gmail.com>
This commit is contained in:
badgerbeesandViet Tran authored and GitHub committed 2026-04-15 17:11:32 +07:00
1 parent ce620c87ef
commit 770af6b1c0
2 files changed
+63 -2

No files matched your search

+48
View File
@@ -0,0 +1,48 @@
import { afterEach, describe, expect, it, vi } from "vitest";
import { HttpClient } from "./http-client";
function createClient() {
return new HttpClient("https://example.com", () => "", () => "");
}
afterEach(() => {
vi.unstubAllGlobals();
localStorage.clear();
});
describe("HttpClient", () => {
it("returns undefined for 204 no-content responses", async () => {
const fetchMock = vi.fn().mockResolvedValue(new Response(null, { status: 204, statusText: "No Content" }));
vi.stubGlobal("fetch", fetchMock as unknown as typeof fetch);
const client = createClient();
const result = await client.delete<void>("/v1/vault/documents/123");
expect(result).toBeUndefined();
expect(fetchMock).toHaveBeenCalledWith(
"https://example.com/v1/vault/documents/123",
expect.objectContaining({
method: "DELETE",
headers: expect.objectContaining({
"Content-Type": "application/json",
}),
}),
);
});
it("parses JSON responses from successful requests", async () => {
const payload = { deleted: true };
const fetchMock = vi.fn().mockResolvedValue(
new Response(JSON.stringify(payload), {
status: 200,
headers: { "content-type": "application/json" },
}),
);
vi.stubGlobal("fetch", fetchMock as unknown as typeof fetch);
const client = createClient();
const result = await client.post<{ deleted: boolean }>("/v1/test", { id: "123" });
expect(result).toEqual(payload);
});
});
+15 -2
View File
@@ -90,7 +90,7 @@ export class HttpClient {
throw new ApiError(code, message);
}
return res.json() as Promise<T>;
return this.readJson<T>(res);
}
private buildUrl(path: string, params?: Record<string, string>): string {
@@ -150,6 +150,19 @@ export class HttpClient {
throw new ApiError(code, message);
}
return res.json() as Promise<T>;
return this.readJson<T>(res);
}
private async readJson<T>(res: Response): Promise<T> {
if (res.status === 204 || res.headers.get("content-length") === "0") {
return undefined as T;
}
const text = await res.text();
if (text.trim().length === 0) {
return undefined as T;
}
return JSON.parse(text) as T;
}
}