2
0

my-usage-date-range-dst.test.ts 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. import { describe, expect, it, vi } from "vitest";
  2. import { fromZonedTime } from "date-fns-tz";
  3. const mocks = vi.hoisted(() => ({
  4. getSession: vi.fn(),
  5. getSystemSettings: vi.fn(),
  6. findUsageLogsForKeySlim: vi.fn(),
  7. findUsageLogsForKeyBatch: vi.fn(),
  8. resolveSystemTimezone: vi.fn(),
  9. }));
  10. vi.mock("@/lib/auth", () => ({
  11. getSession: mocks.getSession,
  12. }));
  13. vi.mock("@/repository/system-config", () => ({
  14. getSystemSettings: mocks.getSystemSettings,
  15. }));
  16. vi.mock("@/repository/usage-logs", async (importOriginal) => {
  17. const actual = await importOriginal<typeof import("@/repository/usage-logs")>();
  18. return {
  19. ...actual,
  20. findUsageLogsForKeySlim: mocks.findUsageLogsForKeySlim,
  21. findUsageLogsForKeyBatch: mocks.findUsageLogsForKeyBatch,
  22. };
  23. });
  24. vi.mock("@/lib/utils/timezone", () => ({
  25. resolveSystemTimezone: mocks.resolveSystemTimezone,
  26. }));
  27. describe("my-usage date range parsing", () => {
  28. it("computes exclusive endTime as next local midnight across DST start for batch logs", async () => {
  29. const tz = "America/Los_Angeles";
  30. mocks.resolveSystemTimezone.mockResolvedValue(tz);
  31. mocks.getSession.mockResolvedValue({
  32. key: { id: 1, key: "k" },
  33. user: { id: 1 },
  34. });
  35. mocks.getSystemSettings.mockResolvedValue({
  36. currencyDisplay: "USD",
  37. billingModelSource: "original",
  38. });
  39. mocks.findUsageLogsForKeyBatch.mockResolvedValue({
  40. logs: [],
  41. nextCursor: null,
  42. hasMore: false,
  43. });
  44. const { getMyUsageLogsBatch } = await import("@/actions/my-usage");
  45. const res = await getMyUsageLogsBatch({ startDate: "2024-03-10", endDate: "2024-03-10" });
  46. expect(res.ok).toBe(true);
  47. expect(mocks.findUsageLogsForKeyBatch).toHaveBeenCalledTimes(1);
  48. const args = mocks.findUsageLogsForKeyBatch.mock.calls[0]?.[0];
  49. expect(args.startTime).toBe(fromZonedTime("2024-03-10T00:00:00", tz).getTime());
  50. expect(args.endTime).toBe(fromZonedTime("2024-03-11T00:00:00", tz).getTime());
  51. expect(args.limit).toBe(20);
  52. expect(args.endTime - args.startTime).toBe(23 * 60 * 60 * 1000);
  53. });
  54. it("computes exclusive endTime as next local midnight across DST end for batch logs", async () => {
  55. const tz = "America/Los_Angeles";
  56. mocks.resolveSystemTimezone.mockResolvedValue(tz);
  57. mocks.getSession.mockResolvedValue({
  58. key: { id: 1, key: "k" },
  59. user: { id: 1 },
  60. });
  61. mocks.getSystemSettings.mockResolvedValue({
  62. currencyDisplay: "USD",
  63. billingModelSource: "original",
  64. });
  65. mocks.findUsageLogsForKeyBatch.mockResolvedValue({
  66. logs: [],
  67. nextCursor: null,
  68. hasMore: false,
  69. });
  70. const { getMyUsageLogsBatch } = await import("@/actions/my-usage");
  71. const res = await getMyUsageLogsBatch({ startDate: "2024-11-03", endDate: "2024-11-03" });
  72. expect(res.ok).toBe(true);
  73. expect(mocks.findUsageLogsForKeyBatch).toHaveBeenCalledTimes(1);
  74. const args = mocks.findUsageLogsForKeyBatch.mock.calls[0]?.[0];
  75. expect(args.startTime).toBe(fromZonedTime("2024-11-03T00:00:00", tz).getTime());
  76. expect(args.endTime).toBe(fromZonedTime("2024-11-04T00:00:00", tz).getTime());
  77. expect(args.limit).toBe(20);
  78. expect(args.endTime - args.startTime).toBe(25 * 60 * 60 * 1000);
  79. });
  80. it("computes DST-safe range for legacy page-based logs API", async () => {
  81. const tz = "America/Los_Angeles";
  82. mocks.resolveSystemTimezone.mockResolvedValue(tz);
  83. mocks.getSession.mockResolvedValue({
  84. key: { id: 1, key: "k" },
  85. user: { id: 1 },
  86. });
  87. mocks.getSystemSettings.mockResolvedValue({
  88. currencyDisplay: "USD",
  89. billingModelSource: "original",
  90. });
  91. mocks.findUsageLogsForKeySlim.mockResolvedValue({
  92. logs: [],
  93. total: 0,
  94. });
  95. const { getMyUsageLogs } = await import("@/actions/my-usage");
  96. const res = await getMyUsageLogs({ startDate: "2024-03-10", endDate: "2024-03-10" });
  97. expect(res.ok).toBe(true);
  98. expect(mocks.findUsageLogsForKeySlim).toHaveBeenCalledTimes(1);
  99. const args = mocks.findUsageLogsForKeySlim.mock.calls[0]?.[0];
  100. expect(args.startTime).toBe(fromZonedTime("2024-03-10T00:00:00", tz).getTime());
  101. expect(args.endTime).toBe(fromZonedTime("2024-03-11T00:00:00", tz).getTime());
  102. expect(args.page).toBe(1);
  103. expect(args.pageSize).toBe(20);
  104. });
  105. });