diff --git a/src/components/orders-review-modal.test.tsx b/src/components/orders-review-modal.test.tsx index 9db64ca..b6d2e35 100644 --- a/src/components/orders-review-modal.test.tsx +++ b/src/components/orders-review-modal.test.tsx @@ -5,19 +5,30 @@ vi.mock("@/components/ui/customer-search", () => ({ CustomerSearch: ({ onValueChange, value, + customers, }: { onValueChange: (v: string) => void; value: string; customers: unknown[]; - }) => ( - - ), + }) => { + // Surface the first non-selected customer's id as a data attribute + // so cascade tests can click it specifically. Falls back to + // "cust-new" when there's no other customer in the list. + const others = (customers as Array<{ id: string }>).filter( + (c) => c.id !== value, + ); + const nextId = others[0]?.id ?? "cust-new"; + return ( + + ); + }, })); vi.mock("sonner", () => ({ @@ -688,4 +699,73 @@ describe("OrdersReviewModal", () => { expect(rekeyedRow?.getAttribute("data-pending-removal")).toBe("false"); }); }); + + describe("customer cascade (company + rep)", () => { + const expandedCustomerA: Customer = { + ...baseCustomer, + id: "cust-A", + customer: "Alice Anderson", + company: "comp-A", + expand: { + company: { ...baseCompany, id: "comp-A", company: "Atlas Corp" }, + rep: { id: "user-1", name: "Riya Patel", email: "riya@atlas.test" }, + }, + }; + const expandedCustomerB: Customer = { + ...baseCustomer, + id: "cust-B", + customer: "Bob Brown", + company: "comp-B", + expand: { + company: { ...baseCompany, id: "comp-B", company: "Beacon Ltd" }, + rep: { id: "user-2", name: "Sam Jones", email: "sam@beacon.test" }, + }, + }; + + it("updates Company and Rep labels when the customer changes", () => { + const props = { + ...baseProps(), + customers: [expandedCustomerA, expandedCustomerB], + customer: expandedCustomerA, + order: { ...baseOrder, customer: "cust-A", company: "comp-A", rep: "Riya Patel" }, + }; + render(); + + // Baseline: Company and Rep show the persisted (A) values. + expect(screen.getByText("Atlas Corp")).toBeInTheDocument(); + expect(screen.getByText("Riya Patel")).toBeInTheDocument(); + expect(screen.queryByText("Beacon Ltd")).not.toBeInTheDocument(); + + // Pick customer B. The mock's data-next-id is computed from the + // customer list, so the click will pass cust-B. + fireEvent.click(screen.getByTestId("customer-search-mock")); + + // Company and Rep should now reflect customer B's expands. + expect(screen.getByText("Beacon Ltd")).toBeInTheDocument(); + expect(screen.getByText("Sam Jones")).toBeInTheDocument(); + // The original A values are no longer in the labels. + expect(screen.queryByText("Atlas Corp")).not.toBeInTheDocument(); + expect(screen.queryByText("Riya Patel")).not.toBeInTheDocument(); + }); + + it("marks the modal dirty after a customer change cascades", () => { + const props = { + ...baseProps(), + customers: [expandedCustomerA, expandedCustomerB], + customer: expandedCustomerA, + order: { ...baseOrder, customer: "cust-A", company: "comp-A", rep: "Riya Patel" }, + }; + render(); + + // Find the Save button by accessible name. The modal's primary + // save action is the only one in the footer. + const saveBefore = screen.getByRole("button", { name: /save/i }); + expect(saveBefore).toBeDisabled(); + + fireEvent.click(screen.getByTestId("customer-search-mock")); + + const saveAfter = screen.getByRole("button", { name: /save/i }); + expect(saveAfter).not.toBeDisabled(); + }); + }); });