diff --git a/src/test/domain/work-orders/use-cases/use-work-order-table-mutations.test.tsx b/src/test/domain/work-orders/use-cases/use-work-order-table-mutations.test.tsx index 73729279..6b2b3a64 100644 --- a/src/test/domain/work-orders/use-cases/use-work-order-table-mutations.test.tsx +++ b/src/test/domain/work-orders/use-cases/use-work-order-table-mutations.test.tsx @@ -25,6 +25,11 @@ import { applySchedulePatch, useWorkOrderTableMutations, } from "@/domain/work-orders/use-cases/use-work-order-table-mutations"; +import { toVendorTablePatch } from "@/domain/work-orders/utils/vendor-assignment-patch"; +import { + getClosabilityGaps, + tableRowToClosabilityInput, +} from "@/domain/work-orders/utils/wo-closability"; function delay(ms: number): Promise { return new Promise((resolve) => setTimeout(resolve, ms)); @@ -345,3 +350,116 @@ describe("useWorkOrderTableMutations schedule isAddOn from BE", () => { ); }); }); + +describe("useWorkOrderTableMutations vendor assignment round-trip", () => { + let rowState: WorkOrderTableRow; + + beforeEach(() => { + getById.mockReset(); + update.mockReset(); + patchBoardField.mockReset(); + rowState = { + ...BASE_ROW, + vendorId: "1", + company: "", + tech: "", + completedDate: "2026-07-15", + docStatus: "Yes", + mediaCount: 1, + woNumber: "20260623001", + primaryDispatchStatus: "Refused", + primaryDispatchId: 10, + dispatchRowVersion: "disp-v1", + }; + }); + + it("keeps Company off the gap list when vendor PATCH returns a Pending assignment", async () => { + const returnedRow: WorkOrderTableRow = { + ...rowState, + vendorId: "9", + company: "New Co", + primaryDispatchStatus: "Pending", + primaryDispatchId: 11, + }; + patchBoardField.mockResolvedValue(returnedRow); + + const onPatch = vi.fn(); + const { result } = renderHook( + () => + useWorkOrderTableMutations({ + onPatch, + clearPatch: () => undefined, + getRow: () => rowState, + }), + { wrapper: makeWrapper() }, + ); + + act(() => { + result.current.patchField( + 42, + toVendorTablePatch({ + vendorId: "9", + company: "New Co", + tech: "", + techPhone: "", + }), + ); + }); + + await waitFor(() => + expect(onPatch).toHaveBeenCalledWith( + 42, + expect.objectContaining({ primaryDispatchStatus: "Pending" }), + ), + ); + + expect(patchBoardField).toHaveBeenCalledWith( + 42, + expect.objectContaining({ field: "vendorId", value: "9" }), + ); + const payload = patchBoardField.mock.calls[0]?.[1] as Record; + expect(payload).not.toHaveProperty("primaryDispatchStatus"); + expect(getClosabilityGaps(tableRowToClosabilityInput(returnedRow))).not.toContain("Company"); + }); + + it("keeps a Company gap when vendor PATCH still returns Refused", async () => { + const returnedRow: WorkOrderTableRow = { + ...rowState, + vendorId: "9", + company: "New Co", + primaryDispatchStatus: "Refused", + }; + patchBoardField.mockResolvedValue(returnedRow); + + const onPatch = vi.fn(); + const { result } = renderHook( + () => + useWorkOrderTableMutations({ + onPatch, + clearPatch: () => undefined, + getRow: () => rowState, + }), + { wrapper: makeWrapper() }, + ); + + act(() => { + result.current.patchField( + 42, + toVendorTablePatch({ + vendorId: "9", + company: "New Co", + tech: "", + techPhone: "", + }), + ); + }); + + await waitFor(() => + expect(onPatch).toHaveBeenCalledWith( + 42, + expect.objectContaining({ primaryDispatchStatus: "Refused" }), + ), + ); + expect(getClosabilityGaps(tableRowToClosabilityInput(returnedRow))).toContain("Company"); + }); +});