From c4419a837c163a071b903311e24259909fdf63de Mon Sep 17 00:00:00 2001 From: vorotamoroz Date: Sat, 1 Aug 2026 15:17:45 +0000 Subject: [PATCH] fix: preserve native HTTP body semantics --- src/modules/services/ObsidianAPIService.ts | 15 +++---- .../services/ObsidianAPIService.unit.spec.ts | 43 ++++++++++++++++++- 2 files changed, 47 insertions(+), 11 deletions(-) diff --git a/src/modules/services/ObsidianAPIService.ts b/src/modules/services/ObsidianAPIService.ts index c455d172..11413e88 100644 --- a/src/modules/services/ObsidianAPIService.ts +++ b/src/modules/services/ObsidianAPIService.ts @@ -147,14 +147,9 @@ export class ObsidianAPIService extends InjectableAPIService ({ platform: { isMobile: false, }, + requestUrl: vi.fn(), })); vi.mock("@/deps.ts", () => ({ Platform: mocks.platform, - requestUrl: vi.fn(), + requestUrl: mocks.requestUrl, })); vi.mock("@/deps", () => ({ Platform: mocks.platform, - requestUrl: vi.fn(), + requestUrl: mocks.requestUrl, })); vi.mock("@/modules/essentialObsidian/APILib/ObsHttpHandler", () => ({ @@ -65,3 +66,41 @@ describe("ObsidianAPIService.showWindowOnRight", () => { expect(workspace.revealLeaf).toHaveBeenCalledWith(rightLeaf); }); }); + +describe("ObsidianAPIService.nativeFetch", () => { + it("normalises a typed-array body when the request URL is a string", async () => { + mocks.requestUrl.mockResolvedValue({ + arrayBuffer: new Uint8Array([9, 8, 7]).buffer, + headers: { etag: '"created"' }, + status: 201, + }); + const source = new Uint8Array([0, 1, 2, 3, 4]); + const body = source.subarray(1, 4); + + const response = await createService({}).nativeFetch("http://127.0.0.1:8088/dav/probe.bin", { + body: body as unknown as BodyInit, + headers: { "Content-Type": "application/octet-stream" }, + method: "PUT", + }); + + expect(response.status).toBe(201); + const request = mocks.requestUrl.mock.calls[0][0] as { body?: unknown }; + expect(request.body).toBeInstanceOf(ArrayBuffer); + expect([...new Uint8Array(request.body as ArrayBuffer)]).toEqual([1, 2, 3]); + }); + + it("constructs a bodyless response for a successful DELETE", async () => { + mocks.requestUrl.mockResolvedValue({ + arrayBuffer: new ArrayBuffer(0), + headers: {}, + status: 204, + }); + + const response = await createService({}).nativeFetch("http://127.0.0.1:8088/dav/probe.bin", { + method: "DELETE", + }); + + expect(response.status).toBe(204); + expect(await response.text()).toBe(""); + }); +});