mirror of
https://github.com/Sea-Haven-Industries/shoc-frontend-new.git
synced 2026-10-06 20:32:05 +00:00
Allow empty Appt Time in wizard, table, and slide-over without blocking create or complete. Omit appointment fields without vendorId so create does not hit DispatchRequired.
166 lines
4.9 KiB
TypeScript
166 lines
4.9 KiB
TypeScript
import { fireEvent, screen } from "@testing-library/react";
|
|
import { describe, expect, it, vi } from "vitest";
|
|
import { SlideOverInfoTabEditView } from "@/app/(protected)/workorders/_components/detail/tabs/slide-over-info-tab-edit-view";
|
|
import type { WorkOrderTableRow } from "@/domain/work-orders/types/work-order-table-row";
|
|
import { expandTablePatchToBoardFieldOps } from "@/domain/work-orders/mappers/work-order-board-patch-mapper";
|
|
import { buildSlideOverPatch } from "@/domain/work-orders/utils/slide-over-draft";
|
|
import { renderWithProviders } from "@/test/test-utils";
|
|
|
|
vi.mock("@/app/(protected)/workorders/_components/list/table/cells/site-cell", () => ({
|
|
SiteCell: ({
|
|
additionalContacts,
|
|
onSave,
|
|
}: {
|
|
additionalContacts?: { name: string; phone: string }[];
|
|
onSave: (patch: {
|
|
site: string;
|
|
location: string;
|
|
locationId: string;
|
|
pocName: string;
|
|
pocPhone: string;
|
|
pocNotes: string;
|
|
additionalContacts?: { name: string; phone: string }[];
|
|
}) => void;
|
|
}) => (
|
|
<button
|
|
type="button"
|
|
onClick={() =>
|
|
onSave({
|
|
site: "SEA1",
|
|
location: "Seattle",
|
|
locationId: "loc-1",
|
|
pocName: "Pat",
|
|
pocPhone: "111",
|
|
pocNotes: "",
|
|
additionalContacts: [{ name: "Backup", phone: "555-0101" }],
|
|
})
|
|
}
|
|
>
|
|
save site {additionalContacts?.length ?? 0}
|
|
</button>
|
|
),
|
|
}));
|
|
|
|
vi.mock(
|
|
"@/app/(protected)/workorders/_components/list/table/cells/editable-wo-number-cell",
|
|
() => ({
|
|
EditableWONumberCell: () => null,
|
|
}),
|
|
);
|
|
vi.mock("@/app/(protected)/workorders/_components/list/table/cells/type-cell", () => ({
|
|
TypeCell: () => null,
|
|
}));
|
|
vi.mock("@/app/(protected)/workorders/_components/list/table/cells/assigned-to-cell", () => ({
|
|
AssignedToCell: () => null,
|
|
}));
|
|
vi.mock("@/app/(protected)/workorders/_components/list/table/cells/date-cell", () => ({
|
|
DateCell: () => null,
|
|
}));
|
|
vi.mock("@/app/(protected)/workorders/_components/list/table/cells/appt-time-cell", () => ({
|
|
ApptTimeCell: () => null,
|
|
}));
|
|
vi.mock("@/app/(protected)/workorders/_components/list/table/cells/pm-type-cell", () => ({
|
|
PMTypeCell: () => null,
|
|
}));
|
|
vi.mock("@/app/(protected)/workorders/_components/list/table/cells/vendor-cell", () => ({
|
|
VendorCell: () => null,
|
|
}));
|
|
vi.mock("@/app/(protected)/workorders/_components/list/table/cells/status-cell", () => ({
|
|
StatusCell: () => null,
|
|
}));
|
|
|
|
function baseRow(overrides: Partial<WorkOrderTableRow> = {}): WorkOrderTableRow {
|
|
return {
|
|
id: 42,
|
|
woNumber: "WO-42",
|
|
site: "SEA1",
|
|
type: "PM",
|
|
severity: null,
|
|
dispatcherId: "u1",
|
|
dispatcherName: "Dispatcher",
|
|
scheduledOn: "2026-07-20",
|
|
completedDate: "",
|
|
targetWeek: "",
|
|
dayGroup: "07/20",
|
|
dayLabel: "Mon",
|
|
location: "Seattle",
|
|
locationId: "loc-1",
|
|
pm: "HVAC",
|
|
serviceNotes: "",
|
|
extraServices: [],
|
|
company: "Vendor Co",
|
|
tech: "Tech",
|
|
techPhone: "",
|
|
vendorId: "v1",
|
|
apptStart: "",
|
|
apptEnd: "",
|
|
apptTime: "",
|
|
status: "Scheduled",
|
|
docStatus: "No",
|
|
pocName: "",
|
|
pocPhone: "",
|
|
pocNotes: "",
|
|
additionalContacts: [],
|
|
dueDate: "",
|
|
rescheduleCount: 0,
|
|
carriedOver: 0,
|
|
isAddOn: false,
|
|
originalWeek: "",
|
|
originalDate: "",
|
|
isPastDue: false,
|
|
scheduleWeekOnly: false,
|
|
mediaCount: 0,
|
|
title: "",
|
|
priority: "",
|
|
primaryDispatchId: null,
|
|
rowVersion: "v1",
|
|
dispatchRowVersion: "",
|
|
flagColor: null,
|
|
...overrides,
|
|
};
|
|
}
|
|
|
|
describe("SlideOverInfoTabEditView additional contacts", () => {
|
|
it("passes additionalContacts into SiteCell and persists them on save", () => {
|
|
const onDraftChange = vi.fn();
|
|
const contacts = [{ name: "Existing", phone: "555-0000" }];
|
|
|
|
renderWithProviders(
|
|
<SlideOverInfoTabEditView
|
|
draft={baseRow({ additionalContacts: contacts })}
|
|
users={[]}
|
|
sites={[]}
|
|
vendors={[]}
|
|
pmTypes={[]}
|
|
allOrders={[]}
|
|
onDraftChange={onDraftChange}
|
|
/>,
|
|
{ withAuth: false },
|
|
);
|
|
|
|
expect(screen.getByText("Appt Time (optional)")).toBeInTheDocument();
|
|
expect(screen.getByRole("button", { name: /save site 1/i })).toBeInTheDocument();
|
|
fireEvent.click(screen.getByRole("button", { name: /save site 1/i }));
|
|
|
|
expect(onDraftChange).toHaveBeenCalledWith(
|
|
expect.objectContaining({
|
|
additionalContacts: [{ name: "Backup", phone: "555-0101" }],
|
|
}),
|
|
);
|
|
});
|
|
|
|
it("includes additionalContacts in the slide-over board PATCH ops", () => {
|
|
const baseline = baseRow();
|
|
const draft = baseRow({
|
|
additionalContacts: [{ name: "Backup", phone: "555-0101", notes: "Gate" }],
|
|
});
|
|
const patch = buildSlideOverPatch(draft, baseline);
|
|
|
|
expect(expandTablePatchToBoardFieldOps(patch)).toEqual([
|
|
{
|
|
field: "additionalContacts",
|
|
value: JSON.stringify([{ name: "Backup", phone: "555-0101", notes: "Gate" }]),
|
|
},
|
|
]);
|
|
});
|
|
});
|