shoc-frontend-new/src/test/app/(protected)/workorders/wo-table-row-reorder-keyboard.test.tsx

148 lines
4.2 KiB
TypeScript

import { fireEvent, screen } from "@testing-library/react";
import { describe, expect, it, vi } from "vitest";
import { WoTableRow } from "@/app/(protected)/workorders/_components/list/table/wo-table-row";
import type { WoTableRowHandlers } from "@/app/(protected)/workorders/_components/list/table/wo-table-row";
import type { WorkOrderTableRow } from "@/domain/work-orders/types/work-order-table-row";
import { renderWithProviders } from "@/test/test-utils";
function makeRow(overrides: Partial<WorkOrderTableRow> = {}): WorkOrderTableRow {
return {
id: "1",
woNumber: "WO-1",
site: "BK5",
type: "PM",
severity: null,
dispatcherId: "u1",
dispatcherName: "Alex",
scheduledOn: "2026-07-15",
completedDate: "",
targetWeek: "2026-07-13",
dayGroup: "07/15",
dayLabel: "WED · 07/15",
location: "Lobby",
locationId: "loc-1",
pm: "HVAC",
serviceNotes: "",
extraServices: [],
vendorId: "7",
company: "Acme",
tech: "Sam",
techPhone: "",
apptStart: "",
apptEnd: "",
apptTime: "",
status: "Scheduled",
docStatus: "No",
pocName: "",
pocPhone: "",
pocNotes: "",
dueDate: "",
rescheduleCount: 0,
carriedOver: 0,
originalWeek: "",
originalDate: "",
isPastDue: false,
scheduleWeekOnly: false,
isAddOn: false,
mediaCount: 0,
title: "",
priority: "",
primaryDispatchId: null,
rowVersion: "v1",
dispatchRowVersion: "",
flagColor: null,
additionalContacts: [],
...overrides,
};
}
function handlers(overrides: Partial<WoTableRowHandlers> = {}): WoTableRowHandlers {
return {
onRowClick: vi.fn(),
onView: vi.fn(),
onEdit: vi.fn(),
onOpenMedia: vi.fn(),
onPatch: vi.fn(),
onScheduleDate: vi.fn(),
onScheduleWeek: vi.fn(),
onScheduleRange: vi.fn(),
onOpenSlideOver: vi.fn(),
onReorder: vi.fn(),
onDragStart: vi.fn(),
onDragOver: vi.fn(),
onDrop: vi.fn(),
onDragEnd: vi.fn(),
...overrides,
};
}
function renderRow(
row: WorkOrderTableRow,
allRows: WorkOrderTableRow[],
rowHandlers: WoTableRowHandlers,
) {
return renderWithProviders(
<table>
<tbody>
<WoTableRow
row={row}
allRows={allRows}
users={[]}
sites={[]}
vendors={[]}
pmTypes={["HVAC"]}
isSelected={false}
isFlashing={false}
dragViz={{ dragId: null, overId: null }}
handlers={rowHandlers}
/>
</tbody>
</table>,
{ withAuth: false },
);
}
describe("WoTableRow keyboard reorder", () => {
it("reorders down and up with arrow keys on the grip", () => {
const onReorder = vi.fn();
const first = makeRow({ id: "1", woNumber: "WO-1" });
const second = makeRow({ id: "2", woNumber: "WO-2" });
renderRow(first, [first, second], handlers({ onReorder }));
fireEvent.keyDown(screen.getByRole("button", { name: "Reorder work order WO-1" }), {
key: "ArrowDown",
});
expect(onReorder).toHaveBeenCalledWith("1", "2");
onReorder.mockClear();
fireEvent.keyDown(screen.getByRole("button", { name: "Reorder work order WO-1" }), {
key: "ArrowUp",
});
expect(onReorder).not.toHaveBeenCalled();
});
it("does not reorder a canceled row from the grip", () => {
const onReorder = vi.fn();
const row = makeRow({ status: "Canceled" });
renderRow(row, [row], handlers({ onReorder }));
const grip = screen.getByRole("button", { name: "Reorder work order WO-1" });
expect(grip).toHaveAttribute("aria-disabled", "true");
expect(grip).toHaveAttribute("tabindex", "-1");
fireEvent.keyDown(grip, { key: "ArrowDown" });
expect(onReorder).not.toHaveBeenCalled();
});
it("skips a canceled neighbor when reordering an active row", () => {
const onReorder = vi.fn();
const first = makeRow({ id: "1", woNumber: "WO-1" });
const canceled = makeRow({ id: "2", woNumber: "WO-2", status: "Canceled" });
const third = makeRow({ id: "3", woNumber: "WO-3" });
renderRow(first, [first, canceled, third], handlers({ onReorder }));
fireEvent.keyDown(screen.getByRole("button", { name: "Reorder work order WO-1" }), {
key: "ArrowDown",
});
expect(onReorder).toHaveBeenCalledWith("1", "3");
});
});