diff --git a/src/domain/vendors/api/vendor-company-roster-api.ts b/src/domain/vendors/api/vendor-company-roster-api.ts index fb051bbb..4213db2d 100644 --- a/src/domain/vendors/api/vendor-company-roster-api.ts +++ b/src/domain/vendors/api/vendor-company-roster-api.ts @@ -19,6 +19,7 @@ const OPEN_WORK_ORDER_MESSAGE = async function readConflictBody(error: unknown): Promise { if (!isHTTPError(error)) return undefined; + if (error.data !== undefined && error.data !== null) return error.data; try { return await error.response.json(); } catch { diff --git a/src/test/domain/vendors/api/vendor-company-roster-api.test.ts b/src/test/domain/vendors/api/vendor-company-roster-api.test.ts index f8242703..ed95e3d4 100644 --- a/src/test/domain/vendors/api/vendor-company-roster-api.test.ts +++ b/src/test/domain/vendors/api/vendor-company-roster-api.test.ts @@ -137,6 +137,41 @@ describe("vendorCompanyRosterApi", () => { ); }); + it("classifies a duplicate 409 from parsed error.data when the response body is consumed", async () => { + const conflictError = new Error("HTTPError") as Error & { + __kyHTTPError: true; + data: unknown; + response: { status: number; json: () => Promise; text: () => Promise }; + }; + conflictError.__kyHTTPError = true; + conflictError.data = { + code: "duplicate_vendor_company_name", + message: "Another vendor company already uses that name.", + }; + const consumedBody = () => { + const rejection = Promise.reject(new TypeError("Body has already been consumed")); + rejection.catch(() => {}); + return rejection; + }; + conflictError.response = { + status: 409, + json: () => consumedBody(), + text: () => consumedBody(), + }; + + apiPost.mockRejectedValueOnce(conflictError); + + await expect(vendorCompanyRosterApi.create({ name: "Solo Co" })).rejects.toSatisfy( + (error: unknown) => { + if (!isVendorRosterConflictError(error)) return false; + return ( + error.conflict.kind === "duplicate" && + error.conflict.message === "Another vendor company already uses that name." + ); + }, + ); + }); + it("rethrows non-conflict errors untouched", async () => { const generic = new Error("boom"); apiPost.mockRejectedValueOnce(generic);