Files
pleno-vue/tests/unit/my-wash-start-production.spec.js
T

135 lines
7.8 KiB
JavaScript

import fs from "node:fs";
import { describe, expect, it } from "vitest";
const source = fs.readFileSync("src/views/dashboards/userDashboard/wash/MyWashStart.vue", "utf8");
describe("MyWashStart.vue production recovery contracts", () => {
it("restores local progress before scheduling a server active-wash restore", () => {
expect(source).toContain("const restoredProgress = restoreProgress();");
expect(source).toContain("shouldRestoreServerActiveWash.value = !restoredProgress?.washInProgress;");
expect(source).toContain("scheduleServerActiveWashRestore(restoredProgress ? 1600 : 0);");
expect(source.indexOf("const restoredProgress = restoreProgress();")).toBeLessThan(
source.indexOf("scheduleServerActiveWashRestore(restoredProgress ? 1600 : 0);")
);
});
it("restores authenticated server active washes into in-progress state and summary data", () => {
expect(source).toContain('const SERVER_ACTIVE_WASH_ENDPOINT = "/modules/self-serve/lane/wash/my-active-wash";');
expect(source).toContain("if (!isAuthenticatedCustomerActiveWash(details, customerNumber))");
expect(source).toContain("await applyServerActiveWash(activeWash);");
expect(source).toContain("washInProgress.value = true;");
expect(source).toContain("currentStep.value = shouldRestoreTaskStep ? steps.TASKS : steps.WASH_IN_PROGRESS;");
expect(source).toContain("await fetchWashSummary(summaryParams, false);");
expect(source).toContain('saveProgress("serverActiveWash");');
});
it("restores relay-enabled server sessions to the task checklist", () => {
expect(source).toContain('const SERVER_TASK_RESTORE_STATUSES = new Set(["MACHINE_RELAY_ENABLED"]);');
expect(source).toContain(
'const SERVER_MACHINE_WASH_STATUSES = new Set(["MACHINE_RELAY_ENABLED", "MACHINE_STARTED"]);'
);
expect(source).toContain("const shouldRestoreTaskStep = SERVER_TASK_RESTORE_STATUSES.has(sessionStatus);");
expect(source).toContain("if (shouldRestoreTaskStep && hasMachineTasks.value)");
expect(source).toContain(
"currentStep.value = displayedActiveTasks.value.length > 0 ? steps.TASKS : steps.WASH_IN_PROGRESS;"
);
});
it("does not restore preview-only ready sessions without start evidence", () => {
expect(source).toContain("const hasServerActiveWashStartEvidence = (details: any) =>");
expect(source).toContain("SERVER_MACHINE_WASH_STATUSES.has(sessionStatus)");
expect(source).toContain("session?.machine_relay_enabled === true");
expect(source).toContain("session?.machine_start_triggered === true");
expect(source).toContain("parseServerDateTimeMs(session?.wash_started_at) !== null");
expect(source).toContain("if (!hasServerActiveWashStartEvidence(details))");
});
it("suppresses recent completions so polling and restore do not resurrect a just-finished wash", () => {
expect(source).toContain('const RECENT_COMPLETED_WASH_KEY = "mywash_recent_completed_v1";');
expect(source).toContain("const RECENT_COMPLETED_WASH_SUPPRESSION_MS = 10 * 60 * 1000;");
expect(source).toContain("const finalizeGuidedWashCompletion = (laneId: number | string | null) =>");
expect(source).toContain("markRecentlyCompletedWash(laneId, licensePlateInput.value, getNumericCustomerNumber());");
expect(source).toContain("if (isRecentlyCompletedActiveWash(activeWash))");
expect(source).toContain(
"const recentlyCompletedCurrentWash = isRecentlyCompletedActiveWash({ details, laneId });"
);
expect(source).toContain("if (recentlyCompletedCurrentWash) {");
expect(source).toContain("if (!serverStillMatchesCurrentWash) {");
expect(source).toContain("if (isRestoring.value || isCompletedWashState.value || !nearestDepartment.value)");
});
it("verifies server completion before recovering from a failed stop command", () => {
expect(source).toContain("const waitForStopFailureServerCompletion = async () =>");
expect(source).toContain("const serverCompleted = await waitForStopFailureServerCompletion();");
expect(source).toContain("if (serverCompleted) {");
expect(source).toContain("finalizeGuidedWashCompletion(completingLaneId);");
});
it("keeps active and completed washes visible even if department availability changes", () => {
expect(source).toContain("const shouldShowWashFlow = computed(");
expect(source).toContain("const isCompletedWashState = computed(");
expect(source).toContain("const hasCompletedGuidedWash = ref(false);");
expect(source).toContain("const hasRecentlyCompletedWash = ref(false);");
expect(source).toContain("washInProgress.value ||");
expect(source).toContain("isCompletingWash.value ||");
expect(source).toContain("isCompletedWashState.value");
expect(source).toContain("hasRecentlyCompletedWash.value");
expect(source).toContain('data-testid="self-serve-completed-fallback"');
expect(source).toContain('v-show="isCompletedWashState"');
expect(source).toContain('<template v-if="shouldShowWashFlow && !isCompletedWashState">');
expect(source).toContain('v-model="displayedStep"');
expect(source).toContain("currentStep.value < steps.COMPLETED");
});
it("does not treat the customer's active occupied lane as unavailable", () => {
expect(source).toContain("session: selfServeSession,");
expect(source).toContain("const isCurrentActiveWashLane = (lane: any) =>");
expect(source).toContain("const isSelfServeSessionAllowed = () =>");
expect(source).toContain("const isCurrentAllowedSelfServeLane = (lane: any) =>");
expect(source).toContain("isAllowedSelfServeValue(selfServeSession.value?.allowed)");
expect(source).toContain("selfServeSession.value?.lane_id");
expect(source).toContain("getAllowedSelfServeLaneIds().has(laneId)");
expect(source).toContain(
'(isCurrentActiveWashLane(lane) || isCurrentAllowedSelfServeLane(lane) || lane.status === "AVAILABLE")'
);
});
it("does not auto-complete active washes from polling before the customer completes them", () => {
expect(source).toContain(
"const recentlyCompletedCurrentWash = isRecentlyCompletedActiveWash({ details, laneId });"
);
expect(source).toContain("if (recentlyCompletedCurrentWash) {");
expect(source).toContain("!isCompletingWash.value");
expect(source.indexOf("!isCompletingWash.value")).toBeLessThan(
source.indexOf("clearLocalActiveWashFromServer();", source.indexOf("if (!serverStillMatchesCurrentWash)"))
);
});
it("defaults to machine wash when configured tasks are machine-only and the customer has not chosen manually", () => {
expect(source).toContain("const hasExplicitWashTypeSelection = ref(false);");
expect(source).toContain(
"const hasMachineTasks = computed(() => activeTasks.value.some((task: any) => isMachineTask(task)));"
);
expect(source).toContain("const shouldDefaultToMachineWash = computed(");
expect(source).toContain('radioWashType.value = "Machine";');
});
it("cleans up unload handlers, department refresh, active-wash polling, and footer state on unmount", () => {
expect(source).toContain("unregisterBeforeUnload.value();");
expect(source).toContain("stopAutoRefresh();");
expect(source).toContain("stopActiveWashRefresh();");
expect(source).toContain("markDestroying();");
expect(source).toContain("setShowFooterInContent(true);");
});
it("prevents duplicate fetches and overlapping active-wash sync requests", () => {
expect(source).toContain("if (isVehicleStepNextLoading.value)");
expect(source).toContain("isVehicleStepNextLoading.value = true;");
expect(source).toContain("if (isSyncingActiveWash.value || !washInProgress.value || !washLaneId.value)");
expect(source).toContain("isSyncingActiveWash.value = true;");
expect(source).toContain("isSyncingActiveWash.value = false;");
expect(source).toContain("stopActiveWashRefresh();");
expect(source).toContain("activeWashRefreshInterval.value = window.setInterval");
});
});