2026-08-10 17:12:13 -03:00
|
|
|
import { render, screen } from "@testing-library/react";
|
2026-08-13 16:49:50 -03:00
|
|
|
import userEvent from "@testing-library/user-event";
|
2026-08-10 17:12:13 -03:00
|
|
|
import { describe, expect, it, vi } from "vitest";
|
|
|
|
|
import { WoTableBody } from "@/app/(protected)/workorders/_components/list/table/wo-table-body";
|
|
|
|
|
import type { ReturnTypeOfUseWorkOrdersTableData } from "@/app/(protected)/workorders/_components/list/table/wo-table-types";
|
|
|
|
|
import type { WorkOrderTableRow } from "@/domain/work-orders/types/work-order-table-row";
|
|
|
|
|
|
|
|
|
|
function makeRow(overrides: Partial<WorkOrderTableRow> = {}): WorkOrderTableRow {
|
|
|
|
|
return {
|
|
|
|
|
id: "1",
|
|
|
|
|
woNumber: "24991",
|
|
|
|
|
site: "CLV2",
|
|
|
|
|
type: "PM",
|
2026-08-17 14:57:39 -03:00
|
|
|
severity: null,
|
2026-08-10 17:12:13 -03:00
|
|
|
dispatcherId: "",
|
|
|
|
|
dispatcherName: "",
|
|
|
|
|
scheduledOn: "2026-06-02",
|
2026-08-17 14:57:39 -03:00
|
|
|
completedDate: "",
|
2026-08-10 17:12:13 -03:00
|
|
|
targetWeek: "",
|
|
|
|
|
dayGroup: "06/02",
|
|
|
|
|
dayLabel: "TUE · 06/02",
|
|
|
|
|
location: "Cleveland, OH",
|
|
|
|
|
locationId: "",
|
|
|
|
|
pm: "Backflow",
|
|
|
|
|
serviceNotes: "",
|
|
|
|
|
extraServices: [],
|
|
|
|
|
company: "",
|
|
|
|
|
tech: "",
|
|
|
|
|
techPhone: "",
|
|
|
|
|
apptStart: "",
|
|
|
|
|
apptEnd: "",
|
|
|
|
|
apptTime: "—",
|
|
|
|
|
status: "Incomplete",
|
|
|
|
|
docStatus: "No",
|
|
|
|
|
pocName: "",
|
|
|
|
|
pocPhone: "",
|
|
|
|
|
pocNotes: "",
|
|
|
|
|
dueDate: "",
|
|
|
|
|
rescheduleCount: 0,
|
|
|
|
|
carriedOver: 0,
|
|
|
|
|
originalWeek: "",
|
|
|
|
|
originalDate: "",
|
|
|
|
|
isPastDue: false,
|
|
|
|
|
scheduleWeekOnly: false,
|
|
|
|
|
mediaCount: 0,
|
|
|
|
|
title: "",
|
|
|
|
|
priority: "",
|
|
|
|
|
vendorId: "",
|
|
|
|
|
primaryDispatchId: null,
|
|
|
|
|
rowVersion: "",
|
|
|
|
|
dispatchRowVersion: "",
|
|
|
|
|
flagColor: null,
|
|
|
|
|
...overrides,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function baseTableData(
|
|
|
|
|
overrides: Partial<ReturnTypeOfUseWorkOrdersTableData> = {},
|
|
|
|
|
): ReturnTypeOfUseWorkOrdersTableData {
|
|
|
|
|
return {
|
|
|
|
|
rows: [],
|
|
|
|
|
isLoading: false,
|
|
|
|
|
isFetching: false,
|
|
|
|
|
error: null,
|
|
|
|
|
refetch: vi.fn(),
|
|
|
|
|
advActive: false,
|
|
|
|
|
advResults: [],
|
2026-08-13 16:49:50 -03:00
|
|
|
unassigned: [],
|
2026-08-17 14:57:39 -03:00
|
|
|
unassignedError: null,
|
2026-08-10 17:12:13 -03:00
|
|
|
unscheduled: [],
|
|
|
|
|
displayGroups: [],
|
|
|
|
|
searchActive: false,
|
|
|
|
|
noSearchResults: false,
|
|
|
|
|
isEmptyWeek: false,
|
|
|
|
|
todayKey: null,
|
|
|
|
|
draftDayKey: null,
|
|
|
|
|
draft: null,
|
|
|
|
|
setDraft: vi.fn(),
|
2026-08-13 16:49:50 -03:00
|
|
|
unassignedOpen: true,
|
|
|
|
|
setUnassignedOpen: vi.fn(),
|
2026-08-10 17:12:13 -03:00
|
|
|
unschedOpen: true,
|
|
|
|
|
setUnschedOpen: vi.fn(),
|
|
|
|
|
selectedId: null,
|
|
|
|
|
setSelectedId: vi.fn(),
|
|
|
|
|
selectedRow: null,
|
|
|
|
|
flashId: null,
|
|
|
|
|
triggerFlash: vi.fn(),
|
|
|
|
|
dragViz: null,
|
|
|
|
|
setDragViz: vi.fn(),
|
|
|
|
|
dragState: null,
|
|
|
|
|
patchRow: vi.fn(),
|
|
|
|
|
clearRowPatch: vi.fn(),
|
|
|
|
|
reorderRows: vi.fn(),
|
|
|
|
|
endDrag: vi.fn(),
|
|
|
|
|
startDayDraft: vi.fn(),
|
|
|
|
|
cancelDraft: vi.fn(),
|
|
|
|
|
addRow: vi.fn(),
|
|
|
|
|
scopeTotalCount: 0,
|
|
|
|
|
totalCount: 0,
|
|
|
|
|
search: "",
|
|
|
|
|
...overrides,
|
|
|
|
|
} as ReturnTypeOfUseWorkOrdersTableData;
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-13 16:49:50 -03:00
|
|
|
describe("WoTableBody Unassigned queue (SH-165)", () => {
|
|
|
|
|
it("renders Unassigned above Unscheduled and day groups without duplicate rows", () => {
|
2026-08-10 17:12:13 -03:00
|
|
|
const datedUnassigned = makeRow({ id: "u-dated", woNumber: "24991" });
|
2026-08-13 16:49:50 -03:00
|
|
|
const undatedUnassigned = makeRow({
|
2026-08-10 17:12:13 -03:00
|
|
|
id: "us1",
|
|
|
|
|
woNumber: "25021",
|
|
|
|
|
scheduledOn: "",
|
|
|
|
|
dayGroup: "",
|
|
|
|
|
dayLabel: "",
|
|
|
|
|
});
|
2026-08-13 16:49:50 -03:00
|
|
|
const undatedAssigned = makeRow({
|
|
|
|
|
id: "us-assigned",
|
|
|
|
|
woNumber: "25022",
|
|
|
|
|
dispatcherId: "sarah",
|
|
|
|
|
dispatcherName: "Sarah",
|
|
|
|
|
scheduledOn: "",
|
|
|
|
|
dayGroup: "",
|
|
|
|
|
dayLabel: "",
|
|
|
|
|
});
|
|
|
|
|
const datedAssigned = makeRow({
|
|
|
|
|
id: "day-assigned",
|
|
|
|
|
woNumber: "25023",
|
|
|
|
|
dispatcherId: "sarah",
|
|
|
|
|
dispatcherName: "Sarah",
|
|
|
|
|
});
|
2026-08-10 17:12:13 -03:00
|
|
|
|
|
|
|
|
const tableData = baseTableData({
|
2026-08-13 16:49:50 -03:00
|
|
|
unassigned: [datedUnassigned, undatedUnassigned],
|
|
|
|
|
unscheduled: [undatedAssigned],
|
2026-08-10 17:12:13 -03:00
|
|
|
displayGroups: [
|
|
|
|
|
{
|
|
|
|
|
key: "06/02",
|
|
|
|
|
label: "TUE · 06/02",
|
|
|
|
|
date: "2026-06-02",
|
2026-08-13 16:49:50 -03:00
|
|
|
items: [datedAssigned],
|
2026-08-10 17:12:13 -03:00
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
render(
|
|
|
|
|
<table>
|
|
|
|
|
<WoTableBody
|
|
|
|
|
tableData={tableData}
|
|
|
|
|
renderRow={(row) => (
|
|
|
|
|
<tr key={String(row.id)} data-testid={`row-${row.id}`}>
|
|
|
|
|
<td>{row.woNumber}</td>
|
|
|
|
|
</tr>
|
|
|
|
|
)}
|
|
|
|
|
renderInlineRow={() => null}
|
|
|
|
|
/>
|
|
|
|
|
</table>,
|
|
|
|
|
);
|
|
|
|
|
|
2026-08-13 16:49:50 -03:00
|
|
|
const unassignedHeader = screen.getByRole("button", {
|
|
|
|
|
name: "Unassigned, 2 work orders, expanded",
|
|
|
|
|
});
|
|
|
|
|
const unscheduledHeader = screen.getByRole("button", {
|
|
|
|
|
name: "Unscheduled, 1 work order, expanded",
|
|
|
|
|
});
|
2026-08-10 17:12:13 -03:00
|
|
|
const dayLabel = screen.getByText("TUE · 06/02");
|
|
|
|
|
|
2026-08-13 16:49:50 -03:00
|
|
|
expect(unassignedHeader.compareDocumentPosition(screen.getByTestId("row-u-dated"))).toBe(
|
|
|
|
|
Node.DOCUMENT_POSITION_FOLLOWING,
|
|
|
|
|
);
|
|
|
|
|
expect(unassignedHeader.compareDocumentPosition(unscheduledHeader)).toBe(
|
|
|
|
|
Node.DOCUMENT_POSITION_FOLLOWING,
|
|
|
|
|
);
|
|
|
|
|
expect(unscheduledHeader.compareDocumentPosition(dayLabel)).toBe(
|
|
|
|
|
Node.DOCUMENT_POSITION_FOLLOWING,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
expect(screen.getByTestId("row-u-dated")).toBeInTheDocument();
|
|
|
|
|
expect(screen.getByTestId("row-us1")).toBeInTheDocument();
|
|
|
|
|
expect(screen.getByTestId("row-us-assigned")).toBeInTheDocument();
|
|
|
|
|
expect(screen.getByTestId("row-day-assigned")).toBeInTheDocument();
|
|
|
|
|
expect(screen.getAllByTestId(/row-/)).toHaveLength(4);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it("collapses and expands the Unassigned section via the disclosure control", async () => {
|
|
|
|
|
const user = userEvent.setup();
|
|
|
|
|
const setUnassignedOpen = vi.fn();
|
|
|
|
|
const tableData = baseTableData({
|
|
|
|
|
unassigned: [makeRow({ id: "u1", woNumber: "24991" })],
|
|
|
|
|
setUnassignedOpen,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
render(
|
|
|
|
|
<table>
|
|
|
|
|
<WoTableBody
|
|
|
|
|
tableData={tableData}
|
|
|
|
|
renderRow={(row) => (
|
|
|
|
|
<tr key={String(row.id)} data-testid={`row-${row.id}`}>
|
|
|
|
|
<td>{row.woNumber}</td>
|
|
|
|
|
</tr>
|
|
|
|
|
)}
|
|
|
|
|
renderInlineRow={() => null}
|
|
|
|
|
/>
|
|
|
|
|
</table>,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
await user.click(screen.getByRole("button", { name: "Unassigned, 1 work order, expanded" }));
|
|
|
|
|
expect(setUnassignedOpen).toHaveBeenCalledWith(expect.any(Function));
|
2026-08-10 17:12:13 -03:00
|
|
|
});
|
2026-08-17 14:57:39 -03:00
|
|
|
|
|
|
|
|
it("renders a scheduled unassigned WO from outside the selected week in the pin", () => {
|
|
|
|
|
const outOfWeek = makeRow({
|
|
|
|
|
id: "out-week",
|
|
|
|
|
woNumber: "26001",
|
|
|
|
|
scheduledOn: "2026-07-15",
|
|
|
|
|
dayGroup: "07/15",
|
|
|
|
|
dayLabel: "WED · 07/15",
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
render(
|
|
|
|
|
<table>
|
|
|
|
|
<WoTableBody
|
|
|
|
|
tableData={baseTableData({ unassigned: [outOfWeek] })}
|
|
|
|
|
renderRow={(row) => (
|
|
|
|
|
<tr key={String(row.id)} data-testid={`row-${row.id}`}>
|
|
|
|
|
<td>{row.woNumber}</td>
|
|
|
|
|
</tr>
|
|
|
|
|
)}
|
|
|
|
|
renderInlineRow={() => null}
|
|
|
|
|
/>
|
|
|
|
|
</table>,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
expect(screen.getByTestId("row-out-week")).toBeInTheDocument();
|
|
|
|
|
expect(screen.queryByText("WED · 07/15")).not.toBeInTheDocument();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it("keeps the Unassigned pin visible when the queue query fails", () => {
|
|
|
|
|
render(
|
|
|
|
|
<table>
|
|
|
|
|
<WoTableBody
|
|
|
|
|
tableData={baseTableData({
|
|
|
|
|
unassignedError: new Error("queue unavailable"),
|
|
|
|
|
})}
|
|
|
|
|
renderRow={(row) => (
|
|
|
|
|
<tr key={String(row.id)} data-testid={`row-${row.id}`}>
|
|
|
|
|
<td>{row.woNumber}</td>
|
|
|
|
|
</tr>
|
|
|
|
|
)}
|
|
|
|
|
renderInlineRow={() => null}
|
|
|
|
|
/>
|
|
|
|
|
</table>,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
expect(screen.getByText("queue unavailable")).toBeInTheDocument();
|
|
|
|
|
});
|
2026-08-10 17:12:13 -03:00
|
|
|
});
|