mirror of
https://github.com/Sea-Haven-Industries/shoc-frontend-new.git
synced 2026-10-07 16:19:01 +00:00
165 lines
5.4 KiB
TypeScript
165 lines
5.4 KiB
TypeScript
|
|
import { act, fireEvent, render, renderHook, screen } from "@testing-library/react";
|
||
|
|
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||
|
|
import { WizardStepVendorTime } from "@/app/(protected)/workorders/_components/wizard/wizard-step-vendor-time";
|
||
|
|
import { useWizardCreateWithTechnicians } from "@/app/(protected)/workorders/_components/wizard/use-wizard-create-with-technicians";
|
||
|
|
import type { VendorDropdownItem } from "@/domain/work-orders/types/work-order";
|
||
|
|
import {
|
||
|
|
EMPTY_WIZARD_DRAFT,
|
||
|
|
type WorkOrderWizardDraft,
|
||
|
|
} from "@/domain/work-orders/types/work-order-wizard";
|
||
|
|
|
||
|
|
const mutateAsync = vi.fn();
|
||
|
|
|
||
|
|
vi.mock("@/domain/vendors/use-cases/use-add-technicians-to-company", () => ({
|
||
|
|
useAddTechniciansToCompany: () => ({ mutateAsync, isPending: false }),
|
||
|
|
}));
|
||
|
|
|
||
|
|
vi.mock("react-toastify", () => ({ toast: { error: vi.fn(), success: vi.fn() } }));
|
||
|
|
|
||
|
|
const vendors: VendorDropdownItem[] = [
|
||
|
|
{
|
||
|
|
id: 41,
|
||
|
|
companyName: "Vinewood LLC",
|
||
|
|
contactName: "Adam Whyte",
|
||
|
|
tradeSpecialties: "HVAC",
|
||
|
|
address: "1 Market St",
|
||
|
|
distanceMiles: null,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
id: 52,
|
||
|
|
companyName: "Gateway Plumbing",
|
||
|
|
contactName: "Casey Pipe",
|
||
|
|
tradeSpecialties: "Plumbing",
|
||
|
|
address: "",
|
||
|
|
distanceMiles: null,
|
||
|
|
},
|
||
|
|
];
|
||
|
|
|
||
|
|
function draftWith(patch: Partial<WorkOrderWizardDraft>): WorkOrderWizardDraft {
|
||
|
|
return { ...EMPTY_WIZARD_DRAFT, type: "PM", status: "Incomplete", ...patch };
|
||
|
|
}
|
||
|
|
|
||
|
|
describe("WizardStepVendorTime inline technician (SH-364)", () => {
|
||
|
|
it("hides the add action until a company is picked", () => {
|
||
|
|
render(
|
||
|
|
<WizardStepVendorTime
|
||
|
|
draft={draftWith({})}
|
||
|
|
vendors={vendors}
|
||
|
|
onUpdate={vi.fn()}
|
||
|
|
onPatch={vi.fn()}
|
||
|
|
/>,
|
||
|
|
);
|
||
|
|
|
||
|
|
expect(screen.queryByRole("button", { name: "+ Add technician" })).not.toBeInTheDocument();
|
||
|
|
expect(screen.getByRole("button", { name: /pick a company first/i })).toBeDisabled();
|
||
|
|
});
|
||
|
|
|
||
|
|
it("stages a new technician row for the picked company", () => {
|
||
|
|
const onPatch = vi.fn();
|
||
|
|
render(
|
||
|
|
<WizardStepVendorTime
|
||
|
|
draft={draftWith({ vendorCompany: "Vinewood LLC" })}
|
||
|
|
vendors={vendors}
|
||
|
|
onUpdate={vi.fn()}
|
||
|
|
onPatch={onPatch}
|
||
|
|
/>,
|
||
|
|
);
|
||
|
|
|
||
|
|
fireEvent.click(screen.getByRole("button", { name: "+ Add technician" }));
|
||
|
|
expect(onPatch).toHaveBeenCalledWith({ newTechnicians: [{ name: "", phone: "" }] });
|
||
|
|
});
|
||
|
|
|
||
|
|
it("scopes technicians to the picked company", () => {
|
||
|
|
render(
|
||
|
|
<WizardStepVendorTime
|
||
|
|
draft={draftWith({
|
||
|
|
vendorCompany: "Vinewood LLC",
|
||
|
|
newTechnicians: [{ name: "Jordan Lee", phone: "" }],
|
||
|
|
})}
|
||
|
|
vendors={vendors}
|
||
|
|
onUpdate={vi.fn()}
|
||
|
|
onPatch={vi.fn()}
|
||
|
|
/>,
|
||
|
|
);
|
||
|
|
|
||
|
|
expect(screen.getByRole("group", { name: "New Technician 1" })).toBeInTheDocument();
|
||
|
|
fireEvent.click(screen.getByRole("button", { name: /select technician/i }));
|
||
|
|
expect(screen.getByRole("button", { name: "Adam Whyte" })).toBeInTheDocument();
|
||
|
|
expect(screen.queryByRole("button", { name: "Casey Pipe" })).not.toBeInTheDocument();
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
describe("useWizardCreateWithTechnicians (SH-364)", () => {
|
||
|
|
beforeEach(() => {
|
||
|
|
mutateAsync.mockReset();
|
||
|
|
});
|
||
|
|
|
||
|
|
it("creates the work order directly when no technician was staged", () => {
|
||
|
|
const createMutation = { mutate: vi.fn(), isPending: false };
|
||
|
|
const { result } = renderHook(() =>
|
||
|
|
useWizardCreateWithTechnicians({ vendors, patchDraft: vi.fn(), createMutation }),
|
||
|
|
);
|
||
|
|
const draft = draftWith({ vendorCompany: "Vinewood LLC", newTechnicians: [] });
|
||
|
|
|
||
|
|
result.current.mutate(draft);
|
||
|
|
|
||
|
|
expect(mutateAsync).not.toHaveBeenCalled();
|
||
|
|
expect(createMutation.mutate).toHaveBeenCalledWith(draft);
|
||
|
|
});
|
||
|
|
|
||
|
|
it("persists staged technicians first and assigns a single new technician", async () => {
|
||
|
|
mutateAsync.mockResolvedValue([{ ...vendors[0], id: 99, contactName: "Jordan Lee" }]);
|
||
|
|
const createMutation = { mutate: vi.fn(), isPending: false };
|
||
|
|
const patchDraft = vi.fn();
|
||
|
|
const { result } = renderHook(() =>
|
||
|
|
useWizardCreateWithTechnicians({ vendors, patchDraft, createMutation }),
|
||
|
|
);
|
||
|
|
|
||
|
|
await act(async () => {
|
||
|
|
result.current.mutate(
|
||
|
|
draftWith({
|
||
|
|
vendorCompany: "Vinewood LLC",
|
||
|
|
newTechnicians: [
|
||
|
|
{ name: "Jordan Lee", phone: "(314) 555-0199" },
|
||
|
|
{ name: " ", phone: "" },
|
||
|
|
],
|
||
|
|
}),
|
||
|
|
);
|
||
|
|
});
|
||
|
|
|
||
|
|
expect(mutateAsync).toHaveBeenCalledWith({
|
||
|
|
anchorVendorId: 41,
|
||
|
|
technicians: [
|
||
|
|
{ contactName: "Jordan Lee", phone: "(314) 555-0199", tradeSpecialties: "HVAC" },
|
||
|
|
],
|
||
|
|
});
|
||
|
|
const expectedPatch = {
|
||
|
|
newTechnicians: [],
|
||
|
|
vendorId: "99",
|
||
|
|
vendorName: "Vinewood LLC",
|
||
|
|
techPhone: "(314) 555-0199",
|
||
|
|
};
|
||
|
|
expect(patchDraft).toHaveBeenCalledWith(expectedPatch);
|
||
|
|
expect(createMutation.mutate).toHaveBeenCalledWith(expect.objectContaining(expectedPatch));
|
||
|
|
});
|
||
|
|
|
||
|
|
it("does not create the work order when the technician save fails", async () => {
|
||
|
|
mutateAsync.mockRejectedValue(new Error("boom"));
|
||
|
|
const createMutation = { mutate: vi.fn(), isPending: false };
|
||
|
|
const { result } = renderHook(() =>
|
||
|
|
useWizardCreateWithTechnicians({ vendors, patchDraft: vi.fn(), createMutation }),
|
||
|
|
);
|
||
|
|
|
||
|
|
await act(async () => {
|
||
|
|
result.current.mutate(
|
||
|
|
draftWith({
|
||
|
|
vendorCompany: "Vinewood LLC",
|
||
|
|
newTechnicians: [{ name: "Jordan Lee", phone: "" }],
|
||
|
|
}),
|
||
|
|
);
|
||
|
|
});
|
||
|
|
|
||
|
|
expect(createMutation.mutate).not.toHaveBeenCalled();
|
||
|
|
});
|
||
|
|
});
|