mirror of
https://github.com/Sea-Haven-Industries/shoc-frontend-new.git
synced 2026-09-30 06:53:12 +00:00
215 lines
6.9 KiB
TypeScript
215 lines
6.9 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { PENDING_UPLIFT_GAP } from "@/domain/work-orders/utils/wo-closability";
|
|
import {
|
|
AUTOMATIC_LIFECYCLE_STATUSES,
|
|
BOARD_INLINE_STATUSES,
|
|
COMPLETED_DOC_BLOCK_MSG,
|
|
COMPLETED_MEDIA_BLOCK_MSG,
|
|
CREATION_INLINE_STATUSES,
|
|
SCHEDULED_NEEDS_DATE_MSG,
|
|
formatAapCompletedBlockTitle,
|
|
getInlineStatusTransitions,
|
|
getStatusOptionState,
|
|
hasConcreteScheduleDate,
|
|
maybeAutoSchedulePatch,
|
|
mergeAutoSchedulePatch,
|
|
resolveCreationStatus,
|
|
withAutoScheduleStatus,
|
|
} from "@/domain/work-orders/utils/wo-lifecycle-transitions";
|
|
import type { WorkOrderTableRow } from "@/domain/work-orders/types/work-order-table-row";
|
|
|
|
describe("wo-lifecycle-transitions", () => {
|
|
it("lists only manual board statuses: no automatic states and no Canceled (SH-169)", () => {
|
|
expect(BOARD_INLINE_STATUSES).toEqual([
|
|
"En Route",
|
|
"On Site",
|
|
"In Progress",
|
|
"Completed",
|
|
"Rescheduled",
|
|
"Pending Quote",
|
|
]);
|
|
expect(BOARD_INLINE_STATUSES).not.toContain("Canceled");
|
|
for (const automatic of AUTOMATIC_LIFECYCLE_STATUSES) {
|
|
expect(BOARD_INLINE_STATUSES).not.toContain(automatic);
|
|
}
|
|
});
|
|
|
|
it("never offers the current status as a transition (SH-358)", () => {
|
|
expect(getInlineStatusTransitions("On Site")).toEqual([
|
|
"En Route",
|
|
"In Progress",
|
|
"Completed",
|
|
"Rescheduled",
|
|
"Pending Quote",
|
|
]);
|
|
expect(getInlineStatusTransitions("Incomplete")).toEqual(BOARD_INLINE_STATUSES);
|
|
});
|
|
|
|
it("lists AAP creation statuses only", () => {
|
|
expect(CREATION_INLINE_STATUSES).toEqual(["Incomplete", "Pending", "Scheduled"]);
|
|
});
|
|
|
|
it("treats week-only as no concrete schedule date", () => {
|
|
expect(hasConcreteScheduleDate({ scheduledOn: "2026-06-01", scheduleWeekOnly: true })).toBe(
|
|
false,
|
|
);
|
|
expect(hasConcreteScheduleDate({ scheduledOn: "2026-06-01", schedMode: "week" })).toBe(false);
|
|
expect(hasConcreteScheduleDate({ scheduledOn: "—" })).toBe(false);
|
|
expect(hasConcreteScheduleDate({ scheduledOn: "2026-06-01" })).toBe(true);
|
|
});
|
|
|
|
it("disables Scheduled without a concrete date", () => {
|
|
expect(getStatusOptionState({ scheduledOn: "" }, "Scheduled", [])).toEqual({
|
|
disabled: true,
|
|
title: SCHEDULED_NEEDS_DATE_MSG,
|
|
});
|
|
});
|
|
|
|
it("promotes Incomplete/Pending when a concrete date exists", () => {
|
|
expect(
|
|
maybeAutoSchedulePatch({
|
|
status: "Incomplete",
|
|
scheduledOn: "2026-06-01",
|
|
scheduleWeekOnly: false,
|
|
}),
|
|
).toEqual({ status: "Scheduled" });
|
|
expect(
|
|
maybeAutoSchedulePatch({
|
|
status: "Pending",
|
|
scheduledOn: "2026-06-01",
|
|
scheduleWeekOnly: false,
|
|
}),
|
|
).toEqual({ status: "Scheduled" });
|
|
});
|
|
|
|
it("reverts Scheduled without a concrete date to Pending", () => {
|
|
expect(
|
|
maybeAutoSchedulePatch({
|
|
status: "Scheduled",
|
|
scheduledOn: "",
|
|
scheduleWeekOnly: false,
|
|
}),
|
|
).toEqual({ status: "Pending" });
|
|
});
|
|
|
|
it("does not auto-change In Progress when a date exists", () => {
|
|
expect(
|
|
maybeAutoSchedulePatch({
|
|
status: "In Progress",
|
|
scheduledOn: "2026-06-01",
|
|
scheduleWeekOnly: false,
|
|
}),
|
|
).toEqual({});
|
|
});
|
|
|
|
it("merges auto-schedule onto an existing-row patch", () => {
|
|
const row = {
|
|
status: "Incomplete",
|
|
scheduledOn: "",
|
|
scheduleWeekOnly: false,
|
|
} as WorkOrderTableRow;
|
|
expect(
|
|
mergeAutoSchedulePatch(row, { scheduledOn: "2026-06-02", scheduleWeekOnly: false }),
|
|
).toEqual({
|
|
scheduledOn: "2026-06-02",
|
|
scheduleWeekOnly: false,
|
|
status: "Scheduled",
|
|
});
|
|
expect(mergeAutoSchedulePatch(row, { vendorId: "9" })).toEqual({ vendorId: "9" });
|
|
expect(
|
|
mergeAutoSchedulePatch({ ...row, scheduledOn: "2026-06-01" }, { vendorId: "9" }),
|
|
).toEqual({ vendorId: "9" });
|
|
});
|
|
|
|
it("promotes a pre-schedule wizard pick to Scheduled on a dated draft", () => {
|
|
const draft = {
|
|
status: "Scheduled",
|
|
scheduledOn: "2026-06-01",
|
|
scheduleWeekOnly: false,
|
|
};
|
|
expect(withAutoScheduleStatus(draft, { status: "Pending" })).toEqual({ status: "Scheduled" });
|
|
expect(withAutoScheduleStatus(draft, { status: "Incomplete" })).toEqual({
|
|
status: "Scheduled",
|
|
});
|
|
});
|
|
|
|
it("still derives Scheduled when a concrete date is set on a draft", () => {
|
|
const draft = {
|
|
status: "Pending",
|
|
scheduledOn: "",
|
|
scheduleWeekOnly: false,
|
|
};
|
|
expect(
|
|
withAutoScheduleStatus(draft, { scheduledOn: "2026-06-02", scheduleWeekOnly: false }),
|
|
).toEqual({
|
|
scheduledOn: "2026-06-02",
|
|
scheduleWeekOnly: false,
|
|
status: "Scheduled",
|
|
});
|
|
});
|
|
|
|
it("promotes pre-schedule picks on dated rows", () => {
|
|
const row = {
|
|
status: "Scheduled",
|
|
scheduledOn: "2026-06-01",
|
|
scheduleWeekOnly: false,
|
|
} as WorkOrderTableRow;
|
|
expect(mergeAutoSchedulePatch(row, { status: "Pending" })).toEqual({ status: "Scheduled" });
|
|
expect(mergeAutoSchedulePatch(row, { status: "Incomplete" })).toEqual({
|
|
status: "Scheduled",
|
|
});
|
|
});
|
|
|
|
it("still demotes Scheduled when the schedule is cleared", () => {
|
|
const row = {
|
|
status: "Scheduled",
|
|
scheduledOn: "2026-06-01",
|
|
scheduleWeekOnly: false,
|
|
} as WorkOrderTableRow;
|
|
expect(mergeAutoSchedulePatch(row, { scheduledOn: "", scheduleWeekOnly: false })).toEqual({
|
|
scheduledOn: "",
|
|
scheduleWeekOnly: false,
|
|
status: "Pending",
|
|
});
|
|
});
|
|
|
|
it("promotes a Pending create pick to Scheduled when the draft is dated", () => {
|
|
expect(
|
|
resolveCreationStatus({
|
|
status: "Pending",
|
|
scheduledOn: "2026-06-01",
|
|
scheduleWeekOnly: false,
|
|
}),
|
|
).toBe("Scheduled");
|
|
});
|
|
|
|
it("demotes Scheduled without a concrete date at create", () => {
|
|
expect(
|
|
resolveCreationStatus({
|
|
status: "Scheduled",
|
|
scheduledOn: "",
|
|
scheduleWeekOnly: false,
|
|
}),
|
|
).toBe("Pending");
|
|
});
|
|
|
|
it("uses AAP completed tooltip hierarchy", () => {
|
|
expect(formatAapCompletedBlockTitle(["Dispatcher", "Company"])).toBe(
|
|
"Fill in Assigned To, Vendor before completing this work order.",
|
|
);
|
|
expect(formatAapCompletedBlockTitle(["Service"])).toBe(
|
|
"Select a service before completing this work order.",
|
|
);
|
|
expect(formatAapCompletedBlockTitle(["WO number"])).toBe(
|
|
"Assign a real APM number (not SH) before completing this work order.",
|
|
);
|
|
expect(formatAapCompletedBlockTitle([PENDING_UPLIFT_GAP])).toBe(
|
|
"This work order has an uplift pending approval and cannot be completed.",
|
|
);
|
|
expect(formatAapCompletedBlockTitle(["Completion document"])).toBe(COMPLETED_DOC_BLOCK_MSG);
|
|
expect(formatAapCompletedBlockTitle(["At least 1 photo"])).toBe(COMPLETED_MEDIA_BLOCK_MSG);
|
|
expect(formatAapCompletedBlockTitle(["Company", PENDING_UPLIFT_GAP])).toBe(
|
|
"Fill in Vendor before completing this work order.",
|
|
);
|
|
});
|
|
});
|