Files
pleno-vue/tests/unit/use-wash-flow-state.spec.js
T

149 lines
4.9 KiB
JavaScript

import { computed, ref } from "vue";
import { describe, expect, it, vi } from "vitest";
import { useWashFlowState, WASH_STEPS } from "@/composables/useWashFlowState.js";
describe("useWashFlowState", () => {
const createState = (overrides = {}) => {
const state = {
currentStep: ref(WASH_STEPS.VEHICLE),
washInProgress: ref(false),
customerNumberInput: ref("12345"),
licensePlateInput: ref("AB12345"),
vehicleTypeSelect: ref(3),
availableProductIds: ref([3, 4]),
radioLaneOption: ref(7),
radioWashType: ref("Manual"),
nearestDepartment: ref({
id: 1,
lanes: [{ id: 7, status: "AVAILABLE" }],
}),
allVisibleQuestionsAnswered: computed(() => true),
isLoadingSelfServeData: ref(false),
activeTasks: ref([]),
completedTasks: ref({}),
editAnswers: ref(false),
isLaneAvailable: (lane) => lane.status === "AVAILABLE",
isMachineAvailable: () => true,
onStartWash: vi.fn(),
updateLaneAllowedServices: vi.fn(),
...overrides,
};
return {
state,
flow: useWashFlowState(state),
};
};
it("validates the vehicle step against customer, registration, and selected vehicle type", () => {
const { flow, state } = createState();
expect(flow.clickableSteps[WASH_STEPS.VEHICLE]()).toBe(true);
state.customerNumberInput.value = "EC21235";
expect(flow.clickableSteps[WASH_STEPS.VEHICLE]()).toBe(true);
state.availableProductIds.value = ["3", "4"];
state.vehicleTypeSelect.value = 3;
expect(flow.clickableSteps[WASH_STEPS.VEHICLE]()).toBe(true);
state.vehicleTypeSelect.value = 9;
expect(flow.clickableSteps[WASH_STEPS.VEHICLE]()).toBe(true);
state.vehicleTypeSelect.value = null;
expect(flow.clickableSteps[WASH_STEPS.VEHICLE]()).toBe(false);
});
it("allows the selected vehicle type when the department has no product allow-list", () => {
const { flow, state } = createState({
availableProductIds: ref([]),
vehicleTypeSelect: ref(3),
});
expect(flow.clickableSteps[WASH_STEPS.VEHICLE]()).toBe(true);
expect(flow.isNextButtonDisabled()).toBe(false);
state.vehicleTypeSelect.value = null;
expect(flow.clickableSteps[WASH_STEPS.VEHICLE]()).toBe(false);
expect(flow.isNextButtonDisabled()).toBe(true);
});
it("does not require a customer number when the customer number input is hidden", () => {
const { flow, state } = createState({
customerNumberInput: ref(""),
isCustomerNumberRequired: ref(false),
});
expect(flow.clickableSteps[WASH_STEPS.VEHICLE]()).toBe(true);
expect(flow.isNextButtonDisabled()).toBe(false);
state.isCustomerNumberRequired.value = true;
expect(flow.clickableSteps[WASH_STEPS.VEHICLE]()).toBe(false);
expect(flow.isNextButtonDisabled()).toBe(true);
});
it("moves from questions to lane selection after updating allowed services", async () => {
const { flow, state } = createState({
currentStep: ref(WASH_STEPS.QUESTIONS),
editAnswers: ref(true),
});
await flow.handleConfirmNext();
expect(state.updateLaneAllowedServices).toHaveBeenCalledWith(7);
expect(state.editAnswers.value).toBe(false);
expect(state.currentStep.value).toBe(WASH_STEPS.SELECT_LANE);
});
it("keeps the user on questions when allowed service sync fails", async () => {
const { flow, state } = createState({
currentStep: ref(WASH_STEPS.QUESTIONS),
editAnswers: ref(true),
updateLaneAllowedServices: vi.fn(async () => {
throw new Error("Edge gateway command timed out");
}),
});
await flow.handleConfirmNext();
expect(state.updateLaneAllowedServices).toHaveBeenCalledWith(7);
expect(state.editAnswers.value).toBe(false);
expect(state.currentStep.value).toBe(WASH_STEPS.QUESTIONS);
});
it("starts the wash from lane selection and branches to tasks when tasks exist", async () => {
const { flow, state } = createState({
currentStep: ref(WASH_STEPS.SELECT_LANE),
activeTasks: ref([{ id: 99 }]),
radioWashType: ref("Machine"),
isMachineAvailable: () => false,
});
expect(flow.isNextButtonDisabled()).toBe(true);
state.radioWashType.value = "Manual";
expect(flow.isNextButtonDisabled()).toBe(false);
await flow.handleConfirmNext();
expect(state.onStartWash).toHaveBeenCalledWith(7, "AB12345", "12345", WASH_STEPS.TASKS);
});
it("matches string lane selections against numeric lane ids", async () => {
const { flow, state } = createState({
currentStep: ref(WASH_STEPS.QUESTIONS),
radioLaneOption: ref("7"),
});
await flow.handleConfirmNext();
expect(state.updateLaneAllowedServices).toHaveBeenCalledWith(7);
expect(state.currentStep.value).toBe(WASH_STEPS.SELECT_LANE);
expect(flow.isNextButtonDisabled()).toBe(false);
await flow.handleConfirmNext();
expect(state.onStartWash).toHaveBeenCalledWith(7, "AB12345", "12345", WASH_STEPS.WASH_IN_PROGRESS);
});
});