mirror of
https://github.com/Sea-Haven-Industries/shoc-frontend-new.git
synced 2026-10-02 16:43:13 +00:00
103 lines
3 KiB
TypeScript
103 lines
3 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import {
|
|
buildSlideOverPatch,
|
|
isSlideOverDraftDirty,
|
|
} from "@/domain/work-orders/utils/slide-over-draft";
|
|
import type { WorkOrderTableRow } from "@/domain/work-orders/types/work-order-table-row";
|
|
|
|
/**
|
|
* Mirrors the failed-save path: optimistic parent row absorbs the patch, then
|
|
* rolls back, while draft is compared against a frozen pre-save baseline.
|
|
*/
|
|
function afterFailedOptimisticSave(input: {
|
|
baseline: WorkOrderTableRow;
|
|
draft: WorkOrderTableRow;
|
|
optimisticParent: WorkOrderTableRow;
|
|
rolledBackParent: WorkOrderTableRow;
|
|
}) {
|
|
const dirtyAgainstOptimistic = isSlideOverDraftDirty(input.draft, input.optimisticParent);
|
|
const dirtyAgainstBaseline = isSlideOverDraftDirty(input.draft, input.baseline);
|
|
const dirtyAgainstRolledBack = isSlideOverDraftDirty(input.draft, input.rolledBackParent);
|
|
const retryPatch = buildSlideOverPatch(input.draft, input.baseline);
|
|
return {
|
|
dirtyAgainstOptimistic,
|
|
dirtyAgainstBaseline,
|
|
dirtyAgainstRolledBack,
|
|
retryPatch,
|
|
canRetry: dirtyAgainstBaseline && Object.keys(retryPatch).length > 0,
|
|
};
|
|
}
|
|
|
|
function row(overrides: Partial<WorkOrderTableRow> = {}): WorkOrderTableRow {
|
|
return {
|
|
id: 1,
|
|
woNumber: "1001",
|
|
site: "SITE-A",
|
|
type: "PM",
|
|
severity: null,
|
|
dispatcherId: "10",
|
|
dispatcherName: "Alex",
|
|
scheduledOn: "2026-07-16",
|
|
completedDate: "",
|
|
targetWeek: "",
|
|
dayGroup: "2026-07-16",
|
|
dayLabel: "Thu",
|
|
location: "Main",
|
|
locationId: 5,
|
|
pm: "Plumbing",
|
|
serviceNotes: "",
|
|
extraServices: [],
|
|
vendorId: "v1",
|
|
company: "Acme",
|
|
tech: "Sam",
|
|
techPhone: "",
|
|
apptStart: "",
|
|
apptEnd: "",
|
|
apptTime: "09:00",
|
|
status: "Incomplete",
|
|
docStatus: "",
|
|
pocName: "",
|
|
pocPhone: "",
|
|
pocNotes: "",
|
|
additionalContacts: [],
|
|
dueDate: "2026-07-20",
|
|
rescheduleCount: 0,
|
|
carriedOver: 0,
|
|
originalWeek: "",
|
|
originalDate: "",
|
|
isPastDue: false,
|
|
scheduleWeekOnly: false,
|
|
mediaCount: 0,
|
|
title: "",
|
|
priority: "",
|
|
primaryDispatchId: null,
|
|
rowVersion: "rv1",
|
|
dispatchRowVersion: "",
|
|
flagColor: null,
|
|
isAddOn: false,
|
|
upliftSummary: { hasUplift: false, pendingCount: 0 },
|
|
...overrides,
|
|
};
|
|
}
|
|
|
|
describe("slide-over failed-save baseline contract", () => {
|
|
it("stays dirty vs frozen baseline after optimistic parent absorbs the edit", () => {
|
|
const baseline = row({ woNumber: "1001" });
|
|
const draft = row({ woNumber: "2002" });
|
|
const optimisticParent = row({ woNumber: "2002" });
|
|
|
|
const result = afterFailedOptimisticSave({
|
|
baseline,
|
|
draft,
|
|
optimisticParent,
|
|
rolledBackParent: baseline,
|
|
});
|
|
|
|
// Bug the review caught: comparing against optimistic parent clears dirty.
|
|
expect(result.dirtyAgainstOptimistic).toBe(false);
|
|
expect(result.dirtyAgainstBaseline).toBe(true);
|
|
expect(result.dirtyAgainstRolledBack).toBe(true);
|
|
expect(result.canRetry).toBe(true);
|
|
expect(result.retryPatch).toEqual({ woNumber: "2002" });
|
|
});
|
|
});
|