shoc-frontend-new/src/test/domain/work-orders/utils/board-query-params.test.ts
Arthur Bassi fc3e7591dc
Some checks are pending
Frontend checks / Build and test (push) Waiting to run
Frontend checks / governance (push) Waiting to run
Frontend checks / Visual regression (push) Waiting to run
Deploy dev content / Deploy shoc-frontend-new-dev through Terraform (push) Waiting to run
fix(work-orders): add Unscheduled option to Advanced Filters Date range (#181)
* fix(work-orders): add Unscheduled option to Advanced Filters Date range

* fix(work-orders): page unscheduled results server-side

---------

Co-authored-by: Codex Review Integration <codex-review@local.invalid>
Co-authored-by: Alexandre Brandizzi <alex_brandizzi@hotmail.com>
2026-09-15 19:11:35 -03:00

435 lines
15 KiB
TypeScript

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 {
DOC_STATUS_API,
LIFECYCLE_STATUS_API,
WORK_ORDER_TYPE_API,
} from "@/domain/work-orders/types/work-order-board";
import type { WOType } from "@/domain/work-orders/types/work-order-wizard";
import { queryKeys } from "@/infra/query-key/query-key";
import {
BOARD_SEARCH_MAX_PAGE_SIZE,
buildBoardSearchParamsRecord,
toBoardQueryParams,
toBoardSearchQueryParams,
toUnassignedQueueQueryParams,
UNASSIGNED_QUEUE_DATE_FROM,
UNASSIGNED_QUEUE_DATE_TO,
} from "@/domain/work-orders/utils/board-query-params";
describe("toBoardQueryParams", () => {
const baseBar = {
weekMonday: "2026-07-13",
dispatcherIds: new Set<string>(),
types: new Set<WOType>(),
};
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, types: new Set(["PM"]) }, "");
expect(params.types).toEqual([WORK_ORDER_TYPE_API.PM]);
expect(params.overdue).toBeUndefined();
});
it("maps multiple types as union query params", () => {
const params = toBoardQueryParams({ ...baseBar, types: new Set(["PM", "Emergency"]) }, "");
expect(params.types).toEqual([WORK_ORDER_TYPE_API.PM, WORK_ORDER_TYPE_API.Emergency]);
expect(params.overdue).toBeUndefined();
});
it("maps Overdue bar filter to overdue=true without types", () => {
const params = toBoardQueryParams({ ...baseBar, 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 = toBoardQueryParams({ ...baseBar, types: new Set(["PM", "Overdue"]) }, "");
expect(params.types).toEqual([WORK_ORDER_TYPE_API.PM]);
expect(params.overdue).toBe(true);
});
it("omits types when the set is empty", () => {
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("Custom");
expect(params.dateFrom).toBe("2000-01-01");
expect(params.dateTo).toBe("2099-12-31");
expect(params.unscheduledOnly).toBeUndefined();
});
it("forwards chrome pageSize 50 instead of the search max", () => {
const params = toBoardSearchQueryParams({
filters: { ...EMPTY_ADVANCED_FILTERS },
page: 1,
pageSize: 50,
});
expect(params.page).toBe(1);
expect(params.pageSize).toBe(50);
});
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.datePreset).toBe("Custom");
expect(thisWeek.dateFrom).toBe("2000-01-01");
expect(thisWeek.dateTo).toBe("2099-12-31");
});
it("sends unscheduledOnly=true with no faked Custom date window (SH-338)", () => {
const withDefaultRange = toBoardSearchQueryParams({
filters: { ...EMPTY_ADVANCED_FILTERS, unscheduledOnly: true },
});
expect(withDefaultRange.unscheduledOnly).toBe(true);
expect(withDefaultRange.datePreset).toBeUndefined();
expect(withDefaultRange.dateFrom).toBeUndefined();
expect(withDefaultRange.dateTo).toBeUndefined();
const overridingLastWeek = toBoardSearchQueryParams({
filters: {
...EMPTY_ADVANCED_FILTERS,
dateRange: "last-week",
unscheduledOnly: true,
},
});
expect(overridingLastWeek.unscheduledOnly).toBe(true);
expect(overridingLastWeek.datePreset).toBeUndefined();
expect(overridingLastWeek.dateFrom).toBeUndefined();
expect(overridingLastWeek.dateTo).toBeUndefined();
const record = buildBoardSearchParamsRecord(overridingLastWeek);
expect(record.unscheduledOnly).toBe(true);
expect(record).not.toHaveProperty("datePreset");
expect(record).not.toHaveProperty("dateFrom");
expect(record).not.toHaveProperty("dateTo");
});
it("keeps applying every other facet alongside unscheduledOnly", () => {
const params = toBoardSearchQueryParams({
filters: {
...EMPTY_ADVANCED_FILTERS,
unscheduledOnly: true,
statuses: new Set(["Scheduled"]),
severities: new Set([4]),
pmTypes: new Set(["HVAC"]),
},
});
expect(params.unscheduledOnly).toBe(true);
expect(params.statuses).toEqual([LIFECYCLE_STATUS_API.Scheduled]);
expect(params.severities).toEqual([4]);
expect(params.pmTypes).toEqual(["HVAC"]);
});
it("omits unscheduledOnly and keeps the wide Custom default when the toggle is off", () => {
const params = toBoardSearchQueryParams({
filters: { ...EMPTY_ADVANCED_FILTERS, dateRange: "last-week" },
});
expect(params.unscheduledOnly).toBeUndefined();
expect(params.datePreset).toBe("LastWeek");
expect(buildBoardSearchParamsRecord(params)).not.toHaveProperty("unscheduledOnly");
});
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();
expect(params.unscheduledOnly).toBeUndefined();
});
it("maps service types and completion docs onto board search params", () => {
const params = toBoardSearchQueryParams({
filters: {
...EMPTY_ADVANCED_FILTERS,
pmTypes: new Set(["HVAC", "Electrical"]),
docs: new Set(["No", "Yes", "NN"]),
},
});
expect(params.pmTypes).toEqual(["HVAC", "Electrical"]);
expect(params.docStatuses).toEqual([
DOC_STATUS_API.No,
DOC_STATUS_API.Yes,
DOC_STATUS_API.NotNeeded,
]);
});
it("maps each extra advanced-filter facet alone onto board search params", () => {
const severity = toBoardSearchQueryParams({
filters: { ...EMPTY_ADVANCED_FILTERS, severities: new Set([4]) },
});
expect(severity.severities).toEqual([4]);
expect(severity.carriedOver).toBeUndefined();
expect(severity.addOn).toBeUndefined();
expect(severity.pmTypes).toBeUndefined();
expect(severity.docStatuses).toBeUndefined();
const carried = toBoardSearchQueryParams({
filters: { ...EMPTY_ADVANCED_FILTERS, carriedOver: true },
});
expect(carried.carriedOver).toBe(true);
expect(carried.severities).toBeUndefined();
const addOn = toBoardSearchQueryParams({
filters: { ...EMPTY_ADVANCED_FILTERS, addOn: true },
});
expect(addOn.addOn).toBe(true);
expect(addOn.carriedOver).toBeUndefined();
const aveta = toBoardSearchQueryParams({
filters: { ...EMPTY_ADVANCED_FILTERS, avetaOnly: true },
});
expect(aveta.avetaOnly).toBe(true);
const service = toBoardSearchQueryParams({
filters: { ...EMPTY_ADVANCED_FILTERS, pmTypes: new Set(["HVAC"]) },
});
expect(service.pmTypes).toEqual(["HVAC"]);
const docs = toBoardSearchQueryParams({
filters: { ...EMPTY_ADVANCED_FILTERS, docs: new Set(["NN"]) },
});
expect(docs.docStatuses).toEqual([DOC_STATUS_API.NotNeeded]);
});
it("combines extra advanced-filter facets with a status facet on the same request", () => {
const params = toBoardSearchQueryParams({
filters: {
...EMPTY_ADVANCED_FILTERS,
severities: new Set([1]),
carriedOver: true,
addOn: true,
pmTypes: new Set(["HVAC"]),
docs: new Set(["Yes"]),
statuses: new Set(["Scheduled"]),
},
});
expect(params.severities).toEqual([1]);
expect(params.carriedOver).toBe(true);
expect(params.addOn).toBe(true);
expect(params.pmTypes).toEqual(["HVAC"]);
expect(params.docStatuses).toEqual([DOC_STATUS_API.Yes]);
expect(params.statuses).toEqual([LIFECYCLE_STATUS_API.Scheduled]);
const record = buildBoardSearchParamsRecord(params);
expect(record.severities).toEqual([1]);
expect(record.carriedOver).toBe(true);
expect(record.addOn).toBe(true);
expect(record.pmTypes).toEqual(["HVAC"]);
expect(record.docStatuses).toEqual([DOC_STATUS_API.Yes]);
expect(record.statuses).toEqual([LIFECYCLE_STATUS_API.Scheduled]);
});
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(200);
});
});
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[]");
});
});
describe("toUnassignedQueueQueryParams", () => {
it("requests unassigned dispatchers with a Custom range, not the weekly board window", () => {
const params = toUnassignedQueueQueryParams(2);
const record = buildBoardSearchParamsRecord(params);
expect(params.page).toBe(2);
expect(params.pageSize).toBe(BOARD_SEARCH_MAX_PAGE_SIZE);
expect(params.dispatchers).toEqual(["__unassigned__"]);
expect(params.statuses).not.toContain(7);
expect(params.statuses).not.toContain(9);
expect(params.datePreset).toBe("Custom");
expect(params.dateFrom).toBe(UNASSIGNED_QUEUE_DATE_FROM);
expect(params.dateTo).toBe(UNASSIGNED_QUEUE_DATE_TO);
expect(record).not.toHaveProperty("weekStart");
expect(record).not.toHaveProperty("weekEnd");
});
});
describe("boardSearch query-key isolation", () => {
it("separates unscheduledOnly=true from the same facets without it", () => {
const without = toBoardSearchQueryParams({
filters: { ...EMPTY_ADVANCED_FILTERS, rescheduled: true },
});
const withUnscheduled = toBoardSearchQueryParams({
filters: { ...EMPTY_ADVANCED_FILTERS, rescheduled: true, unscheduledOnly: true },
});
expect(queryKeys.workOrders.boardSearch(without)).not.toEqual(
queryKeys.workOrders.boardSearch(withUnscheduled),
);
});
it("separates pages under the same unscheduledOnly filter", () => {
const base = toBoardSearchQueryParams({
filters: { ...EMPTY_ADVANCED_FILTERS, unscheduledOnly: true },
page: 0,
});
const pageOne = { ...base, page: 1 };
expect(queryKeys.workOrders.boardSearch(base)).not.toEqual(
queryKeys.workOrders.boardSearch(pageOne),
);
});
});