/// import { describe, expect, test } from "bun:test"; import { formatZonedDateTime, addZonedCalendarInterval, getDefaultScheduledSendAt, isValidTimeZone, toLocalDateTimeInputValue, zonedDateTimeToInstant, } from "../src/time-zone"; import { EXPENSE_CATEGORIES, formatElapsedSeconds, getEffectiveInvoiceStatus, getDaysPastDue, parseReceiptText, } from "../src"; describe("shared domain behavior", () => { test("exposes the expense category vocabulary", () => { expect(EXPENSE_CATEGORIES).toContain("Professional Services"); }); test("calculates overdue status at day precision", () => { const yesterday = new Date(); yesterday.setDate(yesterday.getDate() - 1); expect(getEffectiveInvoiceStatus("sent", yesterday)).toBe("overdue"); expect(getEffectiveInvoiceStatus("paid", yesterday)).toBe("paid"); }); test("counts calendar days rather than 24-hour blocks across fall DST", () => { expect( getDaysPastDue( "sent", "2026-11-01", "America/New_York", new Date("2026-11-02T17:00:00.000Z"), ), ).toBe(1); }); test("formats elapsed time", () => { expect(formatElapsedSeconds(3_661)).toBe("01:01:01"); }); test("extracts receipt totals and line items", () => { const receipt = parseReceiptText( "Corner Store\nCoffee 3.50\nSubtotal 3.50\nTax 0.31\nTotal 3.81", ); expect(receipt.amount).toBe(3.81); expect(receipt.tax).toBe(0.31); expect(receipt.items[0]?.name).toBe("Coffee"); }); }); describe("time-zone helpers", () => { test("formats the same instant in the selected IANA time zone", () => { const instant = new Date("2026-08-17T16:30:00.000Z"); expect(formatZonedDateTime(instant, "America/New_York")).toContain( "12:30 PM", ); expect(formatZonedDateTime(instant, "America/Los_Angeles")).toContain( "9:30 AM", ); }); test("validates IANA time zones", () => { expect(isValidTimeZone("America/New_York")).toBe(true); expect(isValidTimeZone("not/a-zone")).toBe(false); }); test("converts Eastern wall time to the correct absolute instant", () => { expect( zonedDateTimeToInstant( "2026-08-17T09:00", "America/New_York", ).toISOString(), ).toBe("2026-08-17T13:00:00.000Z"); }); test("rejects nonexistent spring-forward wall times", () => { expect(() => zonedDateTimeToInstant("2026-03-08T02:30", "America/New_York"), ).toThrow("does not exist"); }); test("disambiguates both occurrences of a fall-back wall time", () => { expect( zonedDateTimeToInstant( "2026-11-01T01:30", "America/New_York", "earlier", ).toISOString(), ).toBe("2026-11-01T05:30:00.000Z"); expect( zonedDateTimeToInstant( "2026-11-01T01:30", "America/New_York", "later", ).toISOString(), ).toBe("2026-11-01T06:30:00.000Z"); }); test("supports half-hour DST transitions", () => { const earlier = zonedDateTimeToInstant( "2026-04-05T01:45", "Australia/Lord_Howe", "earlier", ); const later = zonedDateTimeToInstant( "2026-04-05T01:45", "Australia/Lord_Howe", "later", ); expect(later.getTime() - earlier.getTime()).toBe(30 * 60_000); }); test("preserves Eastern wall time across DST and clamps month end", () => { expect( addZonedCalendarInterval( new Date("2026-03-01T14:00:00.000Z"), "weekly", "America/New_York", ).toISOString(), ).toBe("2026-03-08T13:00:00.000Z"); expect( addZonedCalendarInterval( new Date("2026-01-31T14:00:00.000Z"), "monthly", "America/New_York", ).toISOString(), ).toBe("2026-02-28T14:00:00.000Z"); }); test("rounds the default schedule to the next local hour", () => { const result = getDefaultScheduledSendAt(new Date(2026, 7, 17, 10, 42, 19)); expect(toLocalDateTimeInputValue(result)).toBe("2026-08-17T11:00"); }); });