130 lines
4.7 KiB
JavaScript
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();
|
|
});
|
|
});
|