From d53012abfcfd2601034750c46e9ea81c9dde2f2a Mon Sep 17 00:00:00 2001 From: Rasmus Widing Date: Thu, 18 Sep 2025 14:37:56 +0300 Subject: [PATCH] Handle fetch aborts in API client --- .../tasks/services/tests/taskService.test.ts | 58 ++++++++++++------- .../src/features/shared/apiWithEtag.ts | 4 ++ 2 files changed, 42 insertions(+), 20 deletions(-) diff --git a/archon-ui-main/src/features/projects/tasks/services/tests/taskService.test.ts b/archon-ui-main/src/features/projects/tasks/services/tests/taskService.test.ts index 0df7fc9b..67a50a57 100644 --- a/archon-ui-main/src/features/projects/tasks/services/tests/taskService.test.ts +++ b/archon-ui-main/src/features/projects/tasks/services/tests/taskService.test.ts @@ -51,10 +51,13 @@ describe("taskService", () => { const result = await taskService.createTask(mockTaskData); // Verify the API was called correctly - expect(callAPIWithETag).toHaveBeenCalledWith("/api/tasks", { - method: "POST", - body: JSON.stringify(mockTaskData), - }); + expect(callAPIWithETag).toHaveBeenCalledWith( + "/api/tasks", + expect.objectContaining({ + method: "POST", + body: JSON.stringify(mockTaskData), + }), + ); // Verify the task is properly unwrapped expect(result).toEqual(mockTask); @@ -103,10 +106,13 @@ describe("taskService", () => { const result = await taskService.updateTask(taskId, mockUpdates); // Verify the API was called correctly - expect(callAPIWithETag).toHaveBeenCalledWith(`/api/tasks/${taskId}`, { - method: "PUT", - body: JSON.stringify(mockUpdates), - }); + expect(callAPIWithETag).toHaveBeenCalledWith( + `/api/tasks/${taskId}`, + expect.objectContaining({ + method: "PUT", + body: JSON.stringify(mockUpdates), + }), + ); // Verify the task is properly unwrapped expect(result).toEqual(mockUpdatedTask); @@ -130,10 +136,13 @@ describe("taskService", () => { const result = await taskService.updateTask(taskId, partialUpdate); - expect(callAPIWithETag).toHaveBeenCalledWith(`/api/tasks/${taskId}`, { - method: "PUT", - body: JSON.stringify(partialUpdate), - }); + expect(callAPIWithETag).toHaveBeenCalledWith( + `/api/tasks/${taskId}`, + expect.objectContaining({ + method: "PUT", + body: JSON.stringify(partialUpdate), + }), + ); expect(result.description).toBe(partialUpdate.description); }); @@ -175,10 +184,13 @@ describe("taskService", () => { const result = await taskService.updateTaskStatus(taskId, newStatus); // Verify the API was called correctly - expect(callAPIWithETag).toHaveBeenCalledWith(`/api/tasks/${taskId}`, { - method: "PUT", - body: JSON.stringify({ status: newStatus }), - }); + expect(callAPIWithETag).toHaveBeenCalledWith( + `/api/tasks/${taskId}`, + expect.objectContaining({ + method: "PUT", + body: JSON.stringify({ status: newStatus }), + }), + ); // Verify the task is properly unwrapped expect(result).toEqual(mockUpdatedTask); @@ -203,9 +215,12 @@ describe("taskService", () => { await taskService.deleteTask(taskId); - expect(callAPIWithETag).toHaveBeenCalledWith(`/api/tasks/${taskId}`, { - method: "DELETE", - }); + expect(callAPIWithETag).toHaveBeenCalledWith( + `/api/tasks/${taskId}`, + expect.objectContaining({ + method: "DELETE", + }), + ); }); it("should handle API errors properly", async () => { @@ -251,7 +266,10 @@ describe("taskService", () => { const result = await taskService.getTasksByProject(projectId); - expect(callAPIWithETag).toHaveBeenCalledWith(`/api/projects/${projectId}/tasks`, { signal: undefined }); + expect(callAPIWithETag).toHaveBeenCalledWith( + `/api/projects/${projectId}/tasks`, + expect.objectContaining({ signal: undefined }) + ); expect(result).toEqual(mockTasks); expect(result).toHaveLength(2); }); diff --git a/archon-ui-main/src/features/shared/apiWithEtag.ts b/archon-ui-main/src/features/shared/apiWithEtag.ts index eb10b8d9..1dbc61b7 100644 --- a/archon-ui-main/src/features/shared/apiWithEtag.ts +++ b/archon-ui-main/src/features/shared/apiWithEtag.ts @@ -111,6 +111,10 @@ export async function callAPIWithETag(endpoint: string, options: Re throw error; } + if (error instanceof Error && error.name === "AbortError") { + throw error; + } + throw new APIServiceError( `Failed to call API ${endpoint}: ${error instanceof Error ? error.message : "Unknown error"}`, "NETWORK_ERROR",