import { describe, it, expect } from "vitest"; import { resolveReportsPeriod, parseAccountIds, serializeAccountIds } from "./useReportsPeriod"; describe("resolveReportsPeriod", () => { const fixedToday = new Date("2026-04-14T12:00:00Z"); it("defaults to current civil year when no URL params are set", () => { const result = resolveReportsPeriod(null, null, null, fixedToday); expect(result.from).toBe("2026-01-01"); expect(result.to).toBe("2026-12-31"); expect(result.period).toBe("custom"); }); it("restores state from bookmarked from/to params", () => { const result = resolveReportsPeriod("2025-03-01", "2025-06-30", null, fixedToday); expect(result.from).toBe("2025-03-01"); expect(result.to).toBe("2025-06-30"); expect(result.period).toBe("custom"); }); it("keeps period=yearly alongside explicit from/to", () => { const result = resolveReportsPeriod("2024-01-01", "2024-12-31", "year", fixedToday); expect(result.period).toBe("year"); }); it("ignores malformed dates and falls back to the civil year", () => { const result = resolveReportsPeriod("not-a-date", "also-not", null, fixedToday); expect(result.from).toBe("2026-01-01"); expect(result.to).toBe("2026-12-31"); expect(result.period).toBe("custom"); }); it("resolves preset period values without from/to", () => { const result = resolveReportsPeriod(null, null, "6months", fixedToday); expect(result.period).toBe("6months"); expect(result.from).toBeTruthy(); expect(result.to).toBeTruthy(); }); it("rejects an invalid period string and falls back to civil year custom", () => { const result = resolveReportsPeriod(null, null, "bogus", fixedToday); expect(result.period).toBe("custom"); expect(result.from).toBe("2026-01-01"); }); it("treats `all` as a preset with empty range (service handles the clauses)", () => { const result = resolveReportsPeriod(null, null, "all", fixedToday); expect(result.period).toBe("all"); // Fallback civil year when computeDateRange returns empty expect(result.from).toBe("2026-01-01"); expect(result.to).toBe("2026-12-31"); }); }); describe("parseAccountIds", () => { it("defaults to an empty array (no filter) when the sources param is absent", () => { expect(parseAccountIds(null)).toEqual([]); }); it("defaults to an empty array for an empty string", () => { expect(parseAccountIds("")).toEqual([]); }); it("parses a comma-separated list of ids", () => { expect(parseAccountIds("3,7,12")).toEqual([3, 7, 12]); }); it("trims whitespace around tokens", () => { expect(parseAccountIds(" 3 , 7 ,12")).toEqual([3, 7, 12]); }); it("parses a single id", () => { expect(parseAccountIds("42")).toEqual([42]); }); it("drops non-numeric tokens but keeps the valid ones (rejects non-numeric)", () => { expect(parseAccountIds("3,abc,7")).toEqual([3, 7]); }); it("drops decimal tokens (not a finite integer)", () => { expect(parseAccountIds("3,4.5,7")).toEqual([3, 7]); }); it("drops empty tokens produced by stray/trailing commas", () => { expect(parseAccountIds("3,,7,")).toEqual([3, 7]); }); it("drops exponential/hex-looking tokens that Number() would otherwise coerce", () => { expect(parseAccountIds("3,1e3,0x10,7")).toEqual([3, 7]); }); it("drops unsafe-integer tokens (too large to be a reliable id)", () => { expect(parseAccountIds("3,99999999999999999999,7")).toEqual([3, 7]); }); it("returns an empty array when every token is invalid", () => { expect(parseAccountIds("abc,def")).toEqual([]); }); }); describe("serializeAccountIds", () => { it("joins ids into a comma-separated string", () => { expect(serializeAccountIds([3, 7, 12])).toBe("3,7,12"); }); it("serializes a single id", () => { expect(serializeAccountIds([42])).toBe("42"); }); it("returns null for an empty array so the param is removed (no filter)", () => { expect(serializeAccountIds([])).toBeNull(); }); it("drops invalid entries (e.g. NaN) before serializing", () => { expect(serializeAccountIds([3, NaN, 7])).toBe("3,7"); }); it("returns null when every entry is invalid", () => { expect(serializeAccountIds([NaN, Infinity])).toBeNull(); }); it("round-trips through parseAccountIds", () => { const ids = [1, 2, 3]; expect(parseAccountIds(serializeAccountIds(ids))).toEqual(ids); }); });