classnames.spec.js
1 month ago
dateUtils.spec.js
1 month ago
formatters.spec.js
1 month ago
pluginUtils.spec.js
1 month ago
transformers.spec.js
1 month ago
dateUtils.spec.js
110 lines
| 1 | import { startOfDay, subDays } from "date-fns"; |
| 2 | import { |
| 3 | ALL_TIME_START, |
| 4 | getLastNDays, |
| 5 | getAllTimeRange, |
| 6 | getAnalyticsPresets, |
| 7 | getRangeLabel, |
| 8 | format, |
| 9 | toAnalyticsDate, |
| 10 | } from "../dateUtils"; |
| 11 | |
| 12 | describe("dateUtils", () => { |
| 13 | beforeAll(() => { |
| 14 | // Freeze "now" so tests are deterministic. Picked an arbitrary |
| 15 | // afternoon timestamp to make sure start-of-day math is exercised. |
| 16 | jest.useFakeTimers().setSystemTime(new Date("2026-05-10T16:33:22")); |
| 17 | }); |
| 18 | |
| 19 | afterAll(() => { |
| 20 | jest.useRealTimers(); |
| 21 | }); |
| 22 | |
| 23 | describe("getLastNDays", () => { |
| 24 | it("returns 30 days inclusive of today, both anchored at start-of-day", () => { |
| 25 | const today = startOfDay(new Date()); |
| 26 | const r = getLastNDays(30); |
| 27 | expect(r.from.getTime()).toBe( |
| 28 | startOfDay(subDays(today, 29)).getTime() |
| 29 | ); |
| 30 | expect(r.to.getTime()).toBe(today.getTime()); |
| 31 | }); |
| 32 | |
| 33 | it("handles non-numeric input by returning empty strings", () => { |
| 34 | const r = getLastNDays("not-a-number"); |
| 35 | expect(r).toEqual({ from: "", to: "" }); |
| 36 | }); |
| 37 | }); |
| 38 | |
| 39 | describe("getAllTimeRange", () => { |
| 40 | it("serializes to the same ISO start the all-time data path already uses", () => { |
| 41 | // Wire-format invariant: matches what useTopPerforming.js sends as |
| 42 | // its all-time fallback, so this default does not change the |
| 43 | // request shape on the backend. |
| 44 | const r = getAllTimeRange(); |
| 45 | expect(toAnalyticsDate(r.from)).toBe(ALL_TIME_START); |
| 46 | }); |
| 47 | }); |
| 48 | |
| 49 | describe("getAnalyticsPresets", () => { |
| 50 | it("returns the All Time, Last 7/30/90 days and Last 12 months presets in order", () => { |
| 51 | const presets = getAnalyticsPresets(); |
| 52 | expect(presets.map((p) => p.label)).toEqual([ |
| 53 | "All Time", |
| 54 | "Last 7 days", |
| 55 | "Last 30 days", |
| 56 | "Last 90 days", |
| 57 | "Last 12 months", |
| 58 | ]); |
| 59 | }); |
| 60 | |
| 61 | }); |
| 62 | |
| 63 | describe("getRangeLabel", () => { |
| 64 | it("returns the All Time label for the all-time range", () => { |
| 65 | expect(getRangeLabel(getAllTimeRange())).toBe("All Time"); |
| 66 | }); |
| 67 | |
| 68 | it("returns the Last 30 days label for getLastNDays(30)", () => { |
| 69 | expect(getRangeLabel(getLastNDays(30))).toBe("Last 30 days"); |
| 70 | }); |
| 71 | |
| 72 | it("falls through to formatted dates for a custom range", () => { |
| 73 | expect( |
| 74 | getRangeLabel({ |
| 75 | from: new Date("2025-01-01T00:00:00"), |
| 76 | to: new Date("2025-01-15T00:00:00"), |
| 77 | }) |
| 78 | ).toBe("01/01/2025 - 01/15/2025"); |
| 79 | }); |
| 80 | |
| 81 | it("returns empty string for an empty range", () => { |
| 82 | expect(getRangeLabel({ from: null, to: null })).toBe(""); |
| 83 | expect(getRangeLabel(null)).toBe(""); |
| 84 | }); |
| 85 | }); |
| 86 | |
| 87 | describe("toAnalyticsDate", () => { |
| 88 | it("anchors the date to UTC midnight regardless of local time", () => { |
| 89 | // The frozen system time is 16:33:22 local but the analytics wire |
| 90 | // format must use 00:00:00.000Z so the backend's date-only window |
| 91 | // doesn't drift by a day for east-of-UTC users. |
| 92 | const out = toAnalyticsDate(new Date()); |
| 93 | expect(out).toMatch(/^\d{4}-\d{2}-\d{2}T00:00:00\.000Z$/); |
| 94 | }); |
| 95 | }); |
| 96 | |
| 97 | describe("format", () => { |
| 98 | it("returns 'No Date' for invalid input", () => { |
| 99 | expect(format(null)).toBe("No Date"); |
| 100 | expect(format("not-a-date")).toBe("No Date"); |
| 101 | }); |
| 102 | |
| 103 | it("formats dates per the supplied pattern", () => { |
| 104 | const d = new Date("2026-05-10T00:00:00"); |
| 105 | expect(format(d, "MM/dd/yyyy")).toBe("05/10/2026"); |
| 106 | expect(format(d, "MMM dd, yyyy")).toBe("May 10, 2026"); |
| 107 | }); |
| 108 | }); |
| 109 | }); |
| 110 |