// @vitest-environment jsdom import { nextTick, ref } from "vue"; import { beforeEach, describe, expect, it, vi } from "vitest"; import { mountWithApp } from "./helpers/mountWithApp.js"; const posState = vi.hoisted(() => ({ customerId: null, notes: null, customerName: null, reference: null, reg1: null, reg2: null, reg3: null, customerAttributes: null, orderNotes: null, orderPo: null, orderId: null, selectedOrderBookingId: null, selectedOrderBookingPlate: null, searchAndSelectCustomer: vi.fn(), selectCustomer: vi.fn(), setSelectedOrderBookingSelection: vi.fn(), clearSelectedOrderBookingSelection: vi.fn(), skipSelectedOrderBookingSelection: vi.fn(), isSelectedOrderBookingSkippedForPlate: vi.fn(() => false), })); vi.mock("@/components/shop/POSDepartmentProcess.vue", async () => { posState.customerId = ref(null); posState.notes = ref([]); posState.customerName = ref(""); posState.reference = ref(""); posState.reg1 = ref("AB12345"); posState.reg2 = ref(""); posState.reg3 = ref(""); posState.customerAttributes = ref([]); posState.orderNotes = ref(""); posState.orderPo = ref(""); posState.orderId = ref(null); posState.selectedOrderBookingId = ref(null); posState.selectedOrderBookingPlate = ref(""); posState.selectCustomer.mockImplementation((customer) => { posState.customerId.value = customer?.customerNumber ?? null; posState.customerName.value = customer?.name ?? ""; }); return { customer_id: posState.customerId, notes: posState.notes, isCustomerBarred: vi.fn(() => false), customer_name: posState.customerName, reference: posState.reference, reg_1: posState.reg1, reg_2: posState.reg2, reg_3: posState.reg3, order_notes: posState.orderNotes, order_po: posState.orderPo, order_id: posState.orderId, searchAndSelectCustomer: posState.searchAndSelectCustomer, selectCustomer: posState.selectCustomer, isCustomerSelected: () => Boolean(posState.customerId.value), customer_attributes: posState.customerAttributes, selectedOrderBookingId: posState.selectedOrderBookingId, selectedOrderBookingPlate: posState.selectedOrderBookingPlate, setSelectedOrderBookingSelection: posState.setSelectedOrderBookingSelection, clearSelectedOrderBookingSelection: posState.clearSelectedOrderBookingSelection, skipSelectedOrderBookingSelection: posState.skipSelectedOrderBookingSelection, isSelectedOrderBookingSkippedForPlate: posState.isSelectedOrderBookingSkippedForPlate, }; }); vi.mock("@/components/session/token/SessionUser.vue", () => ({ SessionUser: { adminUser: false, objects: { orders: { columns: { reg_1: { label: "Nummerplade" }, reg_2: { label: "Reg. 2" }, reg_3: { label: "Reg. 3" }, reference: { label: "Reference" }, }, }, global: { language: { customer: "Kunde", select: "Vælg", other: "Andet", no_data: "Ingen data", last_wash: "Sidste vask", copy: "Kopier", have: "Har", have_not: "Har ikke", quantity: "Antal", show: "Vis", hide: "Skjul", }, }, vehicles: { meta: { labels: { single: "Køretøj", }, }, columns: { wash_subscription: { label: "Vaskeabonnement", }, }, }, products: { meta: { labels: { single: "Produkt", }, }, functions: { getProductName: vi.fn(() => "Forvogn"), }, }, }, }, })); import SelectVehicleFormPOS from "@/components/forms/department/pos/SelectVehicleFormPOS.vue"; const linkedVehicle = { id: 7002, reg: "EC21235", customer_id: 12345679, type: 53, wash_subscription: false, addons: { list: [] }, last_order_id: null, }; const unlinkedVehicle = { id: 7001, reg: "AB12345", customer_id: null, type: 53, wash_subscription: false, addons: { list: [] }, last_order_id: null, }; const LicensePlateReg1InputStub = { name: "LicensePlateReg1Input", emits: ["update:vehicleObject", "update:focus", "update:bookingObject", "update:bookingMatches"], methods: { emitUnlinkedVehicle() { this.$emit("update:vehicleObject", { ...unlinkedVehicle }); }, emitLinkedVehicle() { this.$emit("update:vehicleObject", { ...linkedVehicle }); }, }, template: `
`, }; const ExpandableContentBoxStub = { name: "ExpandableContentBox", props: { expanded: { type: Boolean, default: false, }, }, emits: ["update:expanded"], template: `
`, }; const CustomerSearchFieldPosStub = { name: "CustomerSearchFieldPos", props: { showCardPaymentButton: { type: Boolean, default: true, }, }, template: `
`, }; const SimpleStub = { template: "
", }; function mountForm() { return mountWithApp(SelectVehicleFormPOS, { global: { stubs: { CustomerSearchFieldPos: CustomerSearchFieldPosStub, customerSearchFieldPos: CustomerSearchFieldPosStub, ExpandableContentBox: ExpandableContentBoxStub, LicensePlateReg1Input: LicensePlateReg1InputStub, LicensePlateInput: SimpleStub, PosNotes: SimpleStub, OrderContentTable: SimpleStub, OrderItemsTable: SimpleStub, VehicleCustomerSuggestionsPos: SimpleStub, DefaultObjectSelector: SimpleStub, }, }, }); } describe("SelectVehicleFormPOS", () => { beforeEach(() => { posState.customerId.value = null; posState.notes.value = []; posState.customerName.value = ""; posState.reference.value = ""; posState.reg1.value = "AB12345"; posState.reg2.value = ""; posState.reg3.value = ""; posState.customerAttributes.value = []; posState.orderNotes.value = ""; posState.orderPo.value = ""; posState.orderId.value = null; posState.selectedOrderBookingId.value = null; posState.selectedOrderBookingPlate.value = ""; posState.searchAndSelectCustomer.mockClear(); posState.selectCustomer.mockClear(); posState.setSelectedOrderBookingSelection.mockClear(); posState.clearSelectedOrderBookingSelection.mockClear(); posState.skipSelectedOrderBookingSelection.mockClear(); posState.isSelectedOrderBookingSkippedForPlate.mockReset(); posState.isSelectedOrderBookingSkippedForPlate.mockReturnValue(false); }); it("shows a single inline customer selector before a vehicle is linked", () => { const wrapper = mountForm(); expect(wrapper.findAll('[data-testid="customer-search-field-pos-stub"]')).toHaveLength(1); expect(wrapper.findAll('[data-testid="customer-search-card-payment-stub"]')).toHaveLength(1); expect(wrapper.find('[data-testid="expandable-content-box-stub"]').exists()).toBe(false); }); it("keeps a single inline customer selector when an unlinked vehicle card is expanded", async () => { const wrapper = mountForm(); await wrapper.get('[data-testid="emit-unlinked-vehicle"]').trigger("click"); await nextTick(); expect(wrapper.findAll('[data-testid="customer-search-field-pos-stub"]')).toHaveLength(1); expect(wrapper.find('[data-testid="expandable-content-box-stub"]').exists()).toBe(true); await wrapper.get('[data-testid="expandable-toggle"]').trigger("click"); await nextTick(); expect(wrapper.findAll('[data-testid="customer-search-field-pos-stub"]')).toHaveLength(1); expect(wrapper.findAll('[data-testid="customer-search-card-payment-stub"]')).toHaveLength(1); }); it("moves customer selection into the expanded other section for linked vehicles", async () => { const wrapper = mountForm(); await wrapper.get('[data-testid="emit-linked-vehicle"]').trigger("click"); await nextTick(); expect(wrapper.findAll('[data-testid="customer-search-field-pos-stub"]')).toHaveLength(0); await wrapper.get('[data-testid="expandable-toggle"]').trigger("click"); await nextTick(); expect(wrapper.findAll('[data-testid="customer-search-field-pos-stub"]')).toHaveLength(1); expect(wrapper.findAll('[data-testid="customer-search-card-payment-stub"]')).toHaveLength(1); }); });