shoc-frontend-new/src/test/app/(protected)/workorders/wo-table-row-schedule-clear.test.tsx
Arthur Bassi c71d9482ec feat(work-orders): align Schedule On clear with shared demotion path
Board Clear uses empty-week patch; slide-over Save derives Pending via mergeAutoSchedulePatch.
2026-09-09 15:44:49 -03:00

119 lines
3.8 KiB
TypeScript

import { fireEvent, screen } from "@testing-library/react";
import { describe, expect, it, vi } from "vitest";
import { WoTableRowCells } from "@/app/(protected)/workorders/_components/list/table/wo-table-row-cells";
import type { WoTableRowHandlers } from "@/app/(protected)/workorders/_components/list/table/wo-table-row";
import type {
WorkOrderTablePatch,
WorkOrderTableRow,
} from "@/domain/work-orders/types/work-order-table-row";
import { applySchedulePatch } from "@/domain/work-orders/use-cases/use-work-order-table-mutations";
import { mergeAutoSchedulePatch } from "@/domain/work-orders/utils/wo-lifecycle-transitions";
import { renderWithProviders } from "@/test/test-utils";
vi.mock("@/app/(protected)/workorders/_components/list/table/cells/site-cell", () => ({
SiteCell: () => null,
}));
vi.mock(
"@/app/(protected)/workorders/_components/list/table/cells/editable-wo-number-cell",
() => ({
EditableWONumberCell: () => null,
}),
);
vi.mock("@/app/(protected)/workorders/_components/list/table/cells/type-cell", () => ({
TypeCell: () => null,
}));
vi.mock("@/app/(protected)/workorders/_components/list/table/cells/assigned-to-cell", () => ({
AssignedToCell: () => null,
}));
vi.mock("@/app/(protected)/workorders/_components/list/table/cells/date-cell", () => ({
DateCell: ({ onClear }: { onClear?: () => void }) => {
if (!onClear) return null;
return (
<button type="button" onClick={onClear}>
clear schedule
</button>
);
},
}));
vi.mock("@/app/(protected)/workorders/_components/list/table/cells/due-date-cell", () => ({
DueDateCell: () => null,
}));
function renderScheduledRow(
row: WorkOrderTableRow,
onPersist: (id: string | number, patch: WorkOrderTablePatch) => void,
viewOnly = false,
) {
const handlers = {
onScheduleWeek: (id: string | number, week: string) => {
onPersist(id, mergeAutoSchedulePatch(row, applySchedulePatch(week, false)));
},
} as unknown as WoTableRowHandlers;
renderWithProviders(
<table>
<tbody>
<tr>
<WoTableRowCells
row={row}
allRows={[row]}
users={[]}
sites={[]}
viewOnly={viewOnly}
handlers={handlers}
onPatchRow={vi.fn()}
/>
</tr>
</tbody>
</table>,
{ withAuth: false },
);
}
describe("WoTableRowCells Schedule On clear", () => {
it.each([
{ scheduledOn: "2026-09-09", targetWeek: "", scheduleEnd: "" },
{ scheduledOn: "", targetWeek: "2026-09-07", scheduleEnd: "" },
{ scheduledOn: "2026-09-09", targetWeek: "", scheduleEnd: "2026-09-11" },
])("clears a persisted schedule and derives Pending from Scheduled", (schedule) => {
const onPersist = vi.fn();
const row = {
id: 42,
status: "Scheduled",
scheduleWeekOnly: Boolean(schedule.targetWeek),
schedMode: schedule.targetWeek ? "week" : schedule.scheduleEnd ? "range" : "date",
...schedule,
} as WorkOrderTableRow;
renderScheduledRow(row, onPersist);
fireEvent.click(screen.getByRole("button", { name: "clear schedule" }));
expect(onPersist).toHaveBeenCalledWith(
42,
expect.objectContaining({
scheduledOn: "",
scheduleWeekOnly: false,
targetWeek: "",
scheduleEnd: "",
schedMode: undefined,
status: "Pending",
}),
);
});
it.each(["Completed", "Canceled"])("does not expose Clear for a %s row", (status) => {
const row = {
id: 42,
status,
scheduledOn: "2026-09-09",
targetWeek: "",
scheduleEnd: "",
scheduleWeekOnly: false,
schedMode: "date",
} as WorkOrderTableRow;
renderScheduledRow(row, vi.fn(), true);
expect(screen.queryByRole("button", { name: "clear schedule" })).not.toBeInTheDocument();
});
});