import { act, renderHook } from "@testing-library/react"; import { beforeEach, describe, expect, it, vi } from "vitest"; import { toast } from "react-toastify"; import { useSlideOverEditState } from "@/app/(protected)/workorders/_components/detail/use-slide-over-edit-state"; import type { WorkOrderTableRow } from "@/domain/work-orders/types/work-order-table-row"; import { vendorAssignedMessage, workOrderSavedMessage, } from "@/domain/work-orders/utils/work-order-feedback-toasts"; vi.mock("react-toastify", () => ({ toast: { warning: vi.fn(), success: vi.fn(), error: vi.fn(), }, })); function baseRow(overrides: Partial = {}): WorkOrderTableRow { return { id: 100, woNumber: "100", site: "SITE", type: "Emergency", severity: null, dispatcherId: "d1", dispatcherName: "Alex", scheduledOn: "2026-07-16", completedDate: "", targetWeek: "", dayGroup: "2026-07-16", dayLabel: "Thu", location: "Main", locationId: 5, pm: "", serviceNotes: "", extraServices: [], vendorId: "v1", company: "Acme", tech: "Sam", techPhone: "", apptStart: "", apptEnd: "", apptTime: "", status: "Incomplete", docStatus: "", pocName: "", pocPhone: "", pocNotes: "", additionalContacts: [], dueDate: "", rescheduleCount: 0, carriedOver: 0, originalWeek: "", originalDate: "", isPastDue: false, scheduleWeekOnly: false, mediaCount: 0, title: "", priority: "", primaryDispatchId: null, rowVersion: "1", dispatchRowVersion: "", flagColor: null, isAddOn: false, upliftSummary: { hasUplift: false, pendingCount: 0 }, ...overrides, }; } describe("useSlideOverEditState completed lock", () => { beforeEach(() => { vi.clearAllMocks(); }); it("leaves edit mode and refuses commit when the same work order becomes completed", () => { const onSave = vi.fn(); const onClose = vi.fn(); const setTab = vi.fn(); const open = baseRow(); const { result, rerender } = renderHook( ({ row, infoSource }) => useSlideOverEditState({ row, editMode: true, infoSource, onSave, onClose, closeDisabled: false, setTab, }), { initialProps: { row: open, infoSource: open } }, ); expect(result.current.editing).toBe(true); act(() => { result.current.handleDraftChange({ woNumber: "WO-LOCKED" }); }); const completed = baseRow({ status: "Completed", woNumber: "100" }); rerender({ row: completed, infoSource: completed }); expect(result.current.editing).toBe(false); act(() => { result.current.commit(); }); expect(onSave).not.toHaveBeenCalled(); }); it("toasts vendor assigned after a successful save that includes vendorId", () => { const onSave = vi.fn(); const open = baseRow(); const { result } = renderHook(() => useSlideOverEditState({ row: open, editMode: true, infoSource: open, onSave, onClose: vi.fn(), closeDisabled: false, setTab: vi.fn(), }), ); act(() => { result.current.handleDraftChange({ vendorId: "v2", company: "New Co", tech: "Lee" }); }); act(() => { result.current.commit(); }); expect(onSave).toHaveBeenCalled(); expect(toast.success).not.toHaveBeenCalled(); const options = onSave.mock.calls[0][2] as { onSuccess: () => void }; act(() => { options.onSuccess(); }); expect(toast.success).toHaveBeenCalledWith(vendorAssignedMessage()); expect(toast.success).toHaveBeenCalledTimes(1); }); it("toasts generic save after a successful non-vendor slide-over patch", () => { const onSave = vi.fn(); const open = baseRow(); const { result } = renderHook(() => useSlideOverEditState({ row: open, editMode: true, infoSource: open, onSave, onClose: vi.fn(), closeDisabled: false, setTab: vi.fn(), }), ); act(() => { result.current.handleDraftChange({ dispatcherName: "Blair" }); }); act(() => { result.current.commit(); }); const options = onSave.mock.calls[0][2] as { onSuccess: () => void }; act(() => { options.onSuccess(); }); expect(toast.success).toHaveBeenCalledWith(workOrderSavedMessage()); expect(toast.success).not.toHaveBeenCalledWith(vendorAssignedMessage()); }); });