Files
pleno-vue/tests/unit/use-wash-session-actions-production.spec.js
T

130 lines
4.7 KiB
JavaScript

import { describe, expect, it, vi } from "vitest";
import { ref } from "vue";
import { useWashSessionActions } from "@/composables/useWashSessionActions.js";
import { WASH_STEPS } from "@/composables/useWashFlowState.js";
function createActions(overrides = {}) {
const calls = [];
const request = vi.fn(async (_url, _method, body) => {
calls.push(body.command);
return { data: { success: true } };
});
const state = {
request,
alertFn: vi.fn(),
nearestDepartment: ref({ id: 6, lanes: [{ id: 7 }] }),
vehicleTypeSelect: ref(2),
washLaneId: ref(null),
washInProgress: ref(false),
washStartTime: ref(null),
completedDurationMs: ref(null),
now: ref(10_000),
currentStep: ref(WASH_STEPS.SELECT_LANE),
steps: WASH_STEPS,
radioWashType: ref("Manual"),
activeTasks: ref([]),
completedTasks: ref({}),
saveProgress: vi.fn(),
clearProgress: vi.fn(),
startElapsedTimer: vi.fn(),
stopElapsedTimer: vi.fn(),
updateLaneAllowedServices: vi.fn(async () => true),
fetchWashSummary: vi.fn(async () => ({})),
enableMachineRelay: vi.fn(async () => ({ data: { success: true } })),
isServiceAllowed: vi.fn(() => true),
...overrides,
};
return { state, actions: useWashSessionActions(state), calls };
}
describe("useWashSessionActions production commands", () => {
it("starts a manual wash successfully", async () => {
const { state, actions } = createActions();
await expect(actions.onStartWash(7, "ab12345", "12345679")).resolves.toBe(true);
expect(state.updateLaneAllowedServices).toHaveBeenCalledWith(7);
expect(state.request).toHaveBeenCalledWith(
"/modules/self-serve/lane/command",
"post",
expect.objectContaining({ command: "START", license_plate: "AB12345" })
);
expect(state.washInProgress.value).toBe(true);
expect(state.currentStep.value).toBe(WASH_STEPS.WASH_IN_PROGRESS);
expect(state.saveProgress).toHaveBeenCalledWith("onStartWash");
});
it("reports START failure without mutating active wash state", async () => {
const { state, actions } = createActions({
request: vi.fn(async () => ({ data: { success: false, message: "START failed" } })),
});
await expect(actions.onStartWash(7, "AB12345", "12345679")).resolves.toBe(false);
expect(state.washInProgress.value).toBe(false);
expect(state.alertFn).toHaveBeenCalledWith("START failed");
expect(state.saveProgress).not.toHaveBeenCalled();
});
it("enables machine relay after START when machine service is allowed", async () => {
const { state, actions } = createActions({ radioWashType: ref("Machine") });
await expect(actions.onStartWash(7, "AB12345", "12345679")).resolves.toBe(true);
expect(state.enableMachineRelay).toHaveBeenCalledWith(7);
expect(state.washInProgress.value).toBe(true);
});
it("rolls back with STOP when machine relay enable fails", async () => {
const { state, actions, calls } = createActions({
radioWashType: ref("Machine"),
enableMachineRelay: vi.fn(async () => {
throw new Error("relay down");
}),
});
await expect(actions.onStartWash(7, "AB12345", "12345679")).resolves.toBe(false);
expect(calls).toEqual(["START", "STOP"]);
expect(state.washInProgress.value).toBe(false);
expect(state.alertFn).toHaveBeenCalledWith("relay down");
});
it("keeps active state and alerts when STOP fails", async () => {
const request = vi.fn(async (_url, _method, body) =>
body.command === "STOP" ? { data: { success: false, message: "STOP failed" } } : { data: { success: true } }
);
const { state, actions } = createActions({
request,
washInProgress: ref(true),
washLaneId: ref(7),
washStartTime: ref(1_000),
});
await expect(actions.onStopWash(7)).resolves.toBe(false);
expect(state.washInProgress.value).toBe(true);
expect(state.alertFn).toHaveBeenCalledWith("STOP failed");
expect(state.clearProgress).not.toHaveBeenCalled();
});
it("recovers local state when STOP says the lane is already not occupied", async () => {
const request = vi.fn(async () => ({ data: { success: false, message: "Cannot stop lane 7: not occupied" } }));
const { state, actions } = createActions({
request,
washInProgress: ref(true),
washLaneId: ref(7),
washStartTime: ref(1_000),
now: ref(6_000),
});
await expect(actions.onStopWash(7)).resolves.toBe(true);
expect(state.washInProgress.value).toBe(false);
expect(state.washLaneId.value).toBeNull();
expect(state.completedDurationMs.value).toBe(5_000);
expect(state.stopElapsedTimer).toHaveBeenCalled();
expect(state.clearProgress).toHaveBeenCalled();
});
});