diff --git a/ui/litellm-dashboard/src/components/LicenseExpiryBanner.test.tsx b/ui/litellm-dashboard/src/components/LicenseExpiryBanner.test.tsx index 4dc2ffed49c..c22cffa4e17 100644 --- a/ui/litellm-dashboard/src/components/LicenseExpiryBanner.test.tsx +++ b/ui/litellm-dashboard/src/components/LicenseExpiryBanner.test.tsx @@ -19,6 +19,7 @@ const mockGetLicenseInfo = vi.mocked(getLicenseInfo); const FIXED_NOW = new Date("2026-03-15T12:00:00Z").getTime(); let realDateNow: () => number; +let OrigDate: typeof Date; function makeLicense(expirationDate: string) { return { @@ -34,9 +35,8 @@ describe("LicenseExpiryBanner", () => { beforeEach(() => { vi.clearAllMocks(); realDateNow = Date.now; + OrigDate = Date; // capture before patching so we can restore in afterEach Date.now = () => FIXED_NOW; - // Also override new Date() with no args - const OrigDate = Date; const MockDate = class extends OrigDate { constructor(...args: any[]) { if (args.length === 0) { @@ -70,6 +70,7 @@ describe("LicenseExpiryBanner", () => { }); afterEach(() => { + global.Date = OrigDate; Date.now = realDateNow; }); @@ -145,6 +146,18 @@ describe("LicenseExpiryBanner", () => { expect(container.innerHTML).toBe(""); }); + it("should handle expiration_date with a full ISO timestamp (not just date-only)", async () => { + // Backend might return "2026-03-22T15:00:00Z" instead of "2026-03-22" + // The component should strip the time part and still render correctly. + mockGetLicenseInfo.mockResolvedValue(makeLicense("2026-03-22T15:00:00Z")); + + render(); + + expect( + await screen.findByText("Enterprise License Expiring in 8 days") + ).toBeInTheDocument(); + }); + it("should not render when has_license is false", async () => { mockGetLicenseInfo.mockResolvedValue({ ...makeLicense("2026-03-20"), diff --git a/ui/litellm-dashboard/src/components/LicenseExpiryBanner.tsx b/ui/litellm-dashboard/src/components/LicenseExpiryBanner.tsx index 58a7bff32a6..a265a8018d3 100644 --- a/ui/litellm-dashboard/src/components/LicenseExpiryBanner.tsx +++ b/ui/litellm-dashboard/src/components/LicenseExpiryBanner.tsx @@ -23,7 +23,10 @@ export const LicenseExpiryBanner: React.FC = () => { return null; } - const expDate = new Date(licenseInfo.expiration_date + "T23:59:59"); + // Strip any existing time component so we always get a valid date-only base, + // then append end-of-day in UTC to avoid timezone-dependent parsing. + const dateOnly = licenseInfo.expiration_date.split("T")[0]; + const expDate = new Date(dateOnly + "T23:59:59Z"); const now = new Date(); const diffMs = expDate.getTime() - now.getTime(); const daysRemaining = Math.ceil(diffMs / (1000 * 60 * 60 * 24));