import { describe, it, expect, vi } from "vitest"; vi.mock("../services/mm-api-service/company-info.js", () => ({ getCachedTimezoneName: () => "America/New_York", })); import { convertLaborTicketToLocalTimezone, localizeLaborTicketCopyForConnector, } from "./mm-labor-ticket-helpers.js"; import { MMReceiveLaborTicket } from "../services/mm-api-service/types/receive-types.js"; function makeTicket(): MMReceiveLaborTicket { return new MMReceiveLaborTicket({ laborTicketRef: "ref-1", laborTicketId: "lt-1", workOrderId: "WO-1", clockIn: "2024-06-15T18:30:00.000Z", clockOut: "2024-06-15T20:30:00.000Z", transactionDate: "2024-06-15T20:30:00.000Z", createdAt: "2024-06-15T18:00:00.000Z", updatedAt: "2024-06-15T20:31:00.000Z", workOrderOperation: { closedDate: "2024-06-15T20:30:00.000Z", } as MMReceiveLaborTicket["workOrderOperation"], }); } describe("convertLaborTicketToLocalTimezone", () => { it("converts datetime fields in place to the cached zone", () => { const ticket = makeTicket(); const result = convertLaborTicketToLocalTimezone(ticket); expect(result).toBe(ticket); // mutates and returns the same object expect(ticket.clockIn).toBe("2024-06-15T14:30:00.000-04:00"); expect(ticket.clockOut).toBe("2024-06-15T16:30:00.000-04:00"); expect(ticket.workOrderOperation?.closedDate).toBe( "2024-06-15T16:30:00.000-04:00" ); }); it("normalizes missing datetime fields to null", () => { const ticket = new MMReceiveLaborTicket({ clockIn: "2024-06-15T18:30:00.000Z", }); convertLaborTicketToLocalTimezone(ticket); expect(ticket.clockOut).toBeNull(); expect(ticket.transactionDate).toBeNull(); }); }); describe("localizeLaborTicketCopyForConnector", () => { it("returns a localized copy and leaves the original in UTC", () => { const original = makeTicket(); const copy = localizeLaborTicketCopyForConnector(original); expect(copy).not.toBe(original); expect(copy.clockIn).toBe("2024-06-15T14:30:00.000-04:00"); expect(copy.laborTicketRef).toBe("ref-1"); // Original must be untouched — it is written back to MM in UTC expect(original.clockIn).toBe("2024-06-15T18:30:00.000Z"); expect(original.clockOut).toBe("2024-06-15T20:30:00.000Z"); expect(original.updatedAt).toBe("2024-06-15T20:31:00.000Z"); }); it("does not share the nested workOrderOperation with the original", () => { const original = makeTicket(); const copy = localizeLaborTicketCopyForConnector(original); // The closedDate conversion goes through a setter on workOrderOperation; // a shared reference would corrupt the original's UTC value. expect(copy.workOrderOperation?.closedDate).toBe( "2024-06-15T16:30:00.000-04:00" ); expect(original.workOrderOperation?.closedDate).toBe( "2024-06-15T20:30:00.000Z" ); }); it("handles tickets without a workOrderOperation", () => { const original = new MMReceiveLaborTicket({ clockIn: "2024-06-15T18:30:00.000Z", }); const copy = localizeLaborTicketCopyForConnector(original); expect(copy.clockIn).toBe("2024-06-15T14:30:00.000-04:00"); expect(copy.workOrderOperation).toBeUndefined(); expect(original.clockIn).toBe("2024-06-15T18:30:00.000Z"); }); });