import { describe, expect, it } from "vitest"; import { ASSIGNEE_FILTER_UNASSIGNED } from "@/domain/work-orders/types/work-order-list"; import { EMPTY_ADVANCED_FILTERS } from "@/domain/work-orders/types/work-order-advanced-filters"; import { WORK_ORDER_TYPE_API } from "@/domain/work-orders/types/work-order-board"; import { BOARD_SEARCH_MAX_PAGE_SIZE, buildBoardSearchParamsRecord, toBoardQueryParams, toBoardSearchQueryParams, } from "@/domain/work-orders/utils/board-query-params"; describe("toBoardQueryParams", () => { const baseBar = { weekMonday: "2026-07-13", dispatcherIds: new Set(), type: "All" as const, }; it("omits search when shorter than 2 characters", () => { const params = toBoardQueryParams(baseBar, "B"); expect(params.search).toBeUndefined(); expect(params.weekStart).toBe("2026-07-13"); expect(params.weekEnd).toBe("2026-07-17"); }); it("includes trimmed search when length >= 2", () => { const params = toBoardQueryParams(baseBar, " BK5 "); expect(params.search).toBe("BK5"); }); it("maps unassigned dispatcher to __unassigned__", () => { const params = toBoardQueryParams( { ...baseBar, dispatcherIds: new Set([ASSIGNEE_FILTER_UNASSIGNED, "user-guid"]), }, "", ); expect(params.dispatchers).toEqual(["__unassigned__", "user-guid"]); }); it("maps PM type filter to API types", () => { const params = toBoardQueryParams({ ...baseBar, type: "PM" }, ""); expect(params.types).toEqual([WORK_ORDER_TYPE_API.PM]); expect(params.overdue).toBeUndefined(); }); it("maps Overdue bar filter to overdue=true without types", () => { const params = toBoardQueryParams({ ...baseBar, type: "Overdue" }, ""); expect(params.overdue).toBe(true); expect(params.types).toBeUndefined(); }); it("omits types when filter is All", () => { const params = toBoardQueryParams(baseBar, ""); expect(params.types).toBeUndefined(); expect(params.overdue).toBeUndefined(); }); }); describe("toBoardSearchQueryParams", () => { it("defaults page to 0 (0-based pagination)", () => { const params = toBoardSearchQueryParams({ filters: { ...EMPTY_ADVANCED_FILTERS }, }); expect(params.page).toBe(0); expect(params.pageSize).toBe(BOARD_SEARCH_MAX_PAGE_SIZE); expect(params.datePreset).toBe("ThisWeek"); }); it("maps date presets to PascalCase API values", () => { const params = toBoardSearchQueryParams({ filters: { ...EMPTY_ADVANCED_FILTERS, dateRange: "last-3-months" }, }); expect(params.datePreset).toBe("Last3Months"); }); it("includes dateFrom/dateTo only for Custom preset", () => { const custom = toBoardSearchQueryParams({ filters: { ...EMPTY_ADVANCED_FILTERS, dateRange: "custom", customFrom: "2026-06-01", customTo: "2026-06-30", }, }); expect(custom.datePreset).toBe("Custom"); expect(custom.dateFrom).toBe("2026-06-01"); expect(custom.dateTo).toBe("2026-06-30"); const thisWeek = toBoardSearchQueryParams({ filters: { ...EMPTY_ADVANCED_FILTERS, dateRange: "this-week", customFrom: "2026-06-01", customTo: "2026-06-30", }, }); expect(thisWeek.dateFrom).toBeUndefined(); expect(thisWeek.dateTo).toBeUndefined(); }); it("maps Overdue-only advanced filter to overdue=true without types", () => { const params = toBoardSearchQueryParams({ filters: { ...EMPTY_ADVANCED_FILTERS, types: new Set(["Overdue"]), }, }); expect(params.overdue).toBe(true); expect(params.types).toBeUndefined(); }); it("maps Overdue with real types as OR (types + overdue)", () => { const params = toBoardSearchQueryParams({ filters: { ...EMPTY_ADVANCED_FILTERS, types: new Set(["PM", "Overdue"]), }, }); expect(params.types).toEqual([WORK_ORDER_TYPE_API.PM]); expect(params.overdue).toBe(true); }); it("resolves vendor company names to vendorIds", () => { const params = toBoardSearchQueryParams({ filters: { ...EMPTY_ADVANCED_FILTERS, vendorTechs: new Set(["Acme HVAC", "Unknown"]), }, vendorIdsByCompanyName: new Map([["Acme HVAC", 12]]), }); expect(params.vendorIds).toEqual([12]); }); it("omits empty filter arrays", () => { const params = toBoardSearchQueryParams({ filters: { ...EMPTY_ADVANCED_FILTERS }, search: "x", }); expect(params.search).toBeUndefined(); expect(params.sites).toBeUndefined(); expect(params.types).toBeUndefined(); expect(params.overdue).toBeUndefined(); expect(params.dispatchers).toBeUndefined(); expect(params.statuses).toBeUndefined(); expect(params.pmTypes).toBeUndefined(); expect(params.vendorIds).toBeUndefined(); expect(params.docStatuses).toBeUndefined(); expect(params.severities).toBeUndefined(); expect(params.rescheduled).toBeUndefined(); expect(params.carriedOver).toBeUndefined(); expect(params.addOn).toBeUndefined(); expect(params.flagColors).toBeUndefined(); expect(params.internalOnly).toBeUndefined(); expect(params.hasUplift).toBeUndefined(); expect(params.upliftStatuses).toBeUndefined(); }); it("maps severity and uplift facets onto board search params", () => { const params = toBoardSearchQueryParams({ filters: { ...EMPTY_ADVANCED_FILTERS, severities: new Set([1, 3, 5]), rescheduled: true, carriedOver: true, addOn: true, flagColors: new Set(["#EF4444", "#3B82F6"]), internalOnly: true, hasUplift: true, upliftStatuses: new Set(["pending", "approved"]), }, }); expect(params.severities).toEqual([1, 3, 5]); expect(params.rescheduled).toBe(true); expect(params.carriedOver).toBe(true); expect(params.addOn).toBe(true); expect(params.flagColors).toEqual(["#EF4444", "#3B82F6"]); expect(params.internalOnly).toBe(true); expect(params.hasUplift).toBe(true); expect(params.upliftStatuses).toEqual(["pending", "approved"]); }); it("omits upliftStatuses when hasUplift is false", () => { const params = toBoardSearchQueryParams({ filters: { ...EMPTY_ADVANCED_FILTERS, hasUplift: false, upliftStatuses: new Set(["pending"]), }, }); expect(params.hasUplift).toBeUndefined(); expect(params.upliftStatuses).toBeUndefined(); }); it("caps pageSize at BOARD_SEARCH_MAX_PAGE_SIZE", () => { const params = toBoardSearchQueryParams({ filters: { ...EMPTY_ADVANCED_FILTERS }, pageSize: 500, }); expect(params.pageSize).toBe(100); }); }); describe("buildBoardSearchParamsRecord", () => { it("keeps arrays as repeated-key friendly values (not types[])", () => { const record = buildBoardSearchParamsRecord({ weekStart: "2026-07-13", types: [2, 6], overdue: true, dispatchers: ["guid-a", "__unassigned__"], search: "", }); expect(record.types).toEqual([2, 6]); expect(record.overdue).toBe(true); expect(record.dispatchers).toEqual(["guid-a", "__unassigned__"]); expect(record.search).toBeUndefined(); expect(Object.keys(record)).not.toContain("types[]"); }); });