shoc-frontend-new/src/test/app/(protected)/workorders/wo-table-unassigned-queue.test.tsx

233 lines
6.8 KiB
TypeScript

import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { useState } from "react";
import { describe, expect, it, vi } from "vitest";
import { AssignedToCell } from "@/app/(protected)/workorders/_components/list/table/cells/assigned-to-cell";
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 { expandTablePatchToBoardFieldOps } from "@/domain/work-orders/mappers/work-order-board-patch-mapper";
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",
severity: null,
dispatcherId: "",
dispatcherName: "",
scheduledOn: "2026-06-02",
completedDate: "",
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,
isAddOn: false,
originalWeek: "",
originalDate: "",
isPastDue: false,
scheduleWeekOnly: false,
mediaCount: 0,
title: "",
priority: "",
vendorId: "",
primaryDispatchId: null,
rowVersion: "",
dispatchRowVersion: "",
flagColor: null,
additionalContacts: [],
...overrides,
};
}
function baseTableData(
overrides: Partial<ReturnTypeOfUseWorkOrdersTableData> = {},
): ReturnTypeOfUseWorkOrdersTableData {
return {
rows: [],
isLoading: false,
isFetching: false,
error: null,
refetch: vi.fn(),
advActive: false,
advResults: [],
unassigned: [],
unassignedError: null,
unassignedLoading: false,
unscheduled: [],
displayGroups: [],
searchActive: false,
noSearchResults: false,
isEmptyWeek: false,
todayKey: null,
draftDayKey: null,
draft: null,
setDraft: vi.fn(),
unassignedOpen: true,
setUnassignedOpen: vi.fn(),
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;
}
const DISPATCHER = { id: "sarah", name: "Sarah Chen", initials: "SC", color: "#3366cc" };
function DayAssignHarness({
initialRow,
patchBoardField,
}: {
initialRow: WorkOrderTableRow;
patchBoardField: (
id: string | number,
payload: { field: string; value?: string | null },
) => Promise<WorkOrderTableRow>;
}) {
const [row, setRow] = useState(initialRow);
const tableData = baseTableData({
displayGroups: [
{
key: "06/02",
label: "TUE · 06/02",
date: "2026-06-02",
items: [row],
totalCount: 1,
},
],
});
return (
<table>
<WoTableBody
tableData={tableData}
renderRow={(item) => (
<tr key={String(item.id)} data-testid={`row-${item.id}`}>
<td>{item.woNumber}</td>
<td>
<AssignedToCell
dispatcherId={item.dispatcherId}
users={[DISPATCHER]}
highlight={!item.dispatcherId}
onSave={async (id, name) => {
const ops = expandTablePatchToBoardFieldOps({
dispatcherId: id,
dispatcherName: name,
});
const patched = await patchBoardField(item.id, ops[0]!);
setRow({ ...patched, dispatcherId: id, dispatcherName: name });
}}
/>
</td>
</tr>
)}
renderInlineRow={() => null}
/>
</table>
);
}
describe("WoTableBody weekly board (AAP day view)", () => {
it("renders the selected day and keeps dated-unassigned inline, with no Unassigned pin", () => {
const datedUnassigned = makeRow({ id: "u-dated", woNumber: "24991" });
const datedAssigned = makeRow({
id: "day-assigned",
woNumber: "25023",
dispatcherId: "sarah",
dispatcherName: "Sarah",
});
render(
<table>
<WoTableBody
tableData={baseTableData({
displayGroups: [
{
key: "06/02",
label: "TUE · 06/02",
date: "2026-06-02",
items: [datedUnassigned, datedAssigned],
totalCount: 2,
},
],
})}
renderRow={(row) => (
<tr key={String(row.id)} data-testid={`row-${row.id}`}>
<td>{row.woNumber}</td>
</tr>
)}
renderInlineRow={() => null}
/>
</table>,
);
expect(screen.getByText("TUE · 06/02")).toBeInTheDocument();
expect(screen.getByText("2 WOs")).toBeInTheDocument();
expect(screen.queryByRole("button", { name: /Unassigned/ })).not.toBeInTheDocument();
expect(screen.queryByRole("button", { name: /Unscheduled/ })).not.toBeInTheDocument();
expect(screen.getByTestId("row-u-dated")).toBeInTheDocument();
expect(screen.getByTestId("row-day-assigned")).toBeInTheDocument();
});
it("assigns a dated-unassigned row in the day group without a pin section", async () => {
const user = userEvent.setup();
const pinned = makeRow({
id: "u-pin",
woNumber: "24991",
dispatcherId: "",
dispatcherName: "",
rowVersion: "AAAAAAA=",
});
const patchBoardField = vi.fn(async (_id: string | number, payload: { field: string }) => {
expect(payload.field).toBe("assignTo");
return { ...pinned, dispatcherId: DISPATCHER.id, dispatcherName: DISPATCHER.name };
});
render(<DayAssignHarness initialRow={pinned} patchBoardField={patchBoardField} />);
expect(screen.getByTestId("row-u-pin")).toBeInTheDocument();
await user.click(screen.getByRole("button", { name: /Select/ }));
await user.click(screen.getByRole("button", { name: /Sarah Chen/ }));
expect(patchBoardField).toHaveBeenCalled();
expect(screen.queryByRole("button", { name: /Unassigned/ })).not.toBeInTheDocument();
expect(screen.getByTestId("row-u-pin")).toBeInTheDocument();
expect(screen.getByText("TUE · 06/02")).toBeInTheDocument();
});
});